The honest framing
Both work. Both can ship a great app. The choice usually comes down to who you can hire, what libraries you'll need, and how the app surfaces in Thai-language stores and Thai-language search. Performance differences exist but are rarely decisive. We'll walk through five evaluation axes, then map them to use cases.
Axis 1: Hiring pool in Bangkok
This is the one most blog posts skip and the one that decides projects. We track Bangkok job postings and CV inflows monthly:
| Stack | Senior CVs/month (Bangkok) | Median rate (THB/month) | English fluency |
|---|---|---|---|
| React Native | ~85 | ฿120K-180K | High (web crossover) |
| Flutter | ~22 | ฿100K-150K | Mixed |
| Native iOS (Swift) | ~14 | ฿140K-220K | Mixed |
| Native Android (Kotlin) | ~31 | ฿110K-170K | Mixed |
React Native wins decisively on hiring depth. The reason is simple: most Bangkok JS developers can be productive in React Native within 2 weeks. Flutter requires a separate Dart ramp-up, and Dart talent outside Flutter is essentially zero.
If your team already has React/Next.js engineers (most of our case-study clients do), the cost of context-switching to RN is near zero. If you're hiring greenfield, RN still has a 4x larger pool.
Axis 2: Library ecosystem reality
Both ecosystems are mature. Neither is "missing libraries" anymore. But the failure modes differ.
React Native (with Expo)
The Expo SDK has become so good that we use it for every RN project unless the client has a specific reason against it. EAS Build, EAS Update, expo-router, expo-secure-store, expo-image — all production-grade. Native modules outside Expo's umbrella still require care, but the bare-RN nightmare of 2020 is gone.
// expo-router: file-based routing, App Router-style
// app/(tabs)/feed.tsx
import { FlashList } from '@shopify/flash-list'
export default function Feed() {
return <FlashList data={posts} renderItem={...} estimatedItemSize={120} />
}
// app/_layout.tsx
import { Stack } from 'expo-router'
export default function Layout() {
return <Stack screenOptions={{ headerShown: false }} />
}
Flutter
The pub.dev ecosystem is large, but quality varies more than npm. We've hit cases where the top-ranked package is unmaintained for 14 months. Production-critical packages (auth, payments, push) are usually well-maintained by Google or large teams. Long-tail (image cropping, specific banking SDKs) is hit-or-miss.
Flutter's strength is its standard library. Material and Cupertino widgets ship out of the box. RN still requires you to assemble UI from react-native-reanimated, moti, nativewind or similar. For a designer-driven build with a tight timeline, Flutter can save you days.
Axis 3: ASO and store metadata in Thai
This is where most Bangkok teams drop points. Both Apple App Store and Google Play index Thai-language metadata heavily for Thai-locale users — but only if you set it up right. The frameworks themselves are neutral; what matters is your fastlane or EAS Submit config.
// fastlane/metadata/th-TH/description.txt — Thai App Store listing
แอปจัดการนัดหมายร้านสปาในไทย รองรับ PromptPay, ออกใบกำกับภาษีอัตโนมัติ
รองรับสาขาหลายแห่ง พนักงาน Online Booking 24 ชม.
// app.json (Expo) — locale targeting
{
"expo": {
"ios": { "infoPlist": { "CFBundleLocalizations": ["en", "th"] } },
"android": { "config": { "googleMaps": { "apiKey": "..." } } }
}
}
Our SEO partner covers store-listing keyword research; the principles overlap heavily with web SEO but the keyword volumes are lower and conversion intent is much higher.
Axis 4: Thai-language tooling — fonts, line-breaking, IME
Thai script has no spaces between words. Line-breaking is non-trivial. Every cross-platform framework gets this almost right.
React Native
Default text rendering uses platform line-breakers (UICTLineBreakMode on iOS, ICU on Android). Thai breaks correctly out of the box on iOS 16+. Older Android (API ≤ 28) has known issues with mid-word breaks. Workaround:
import { Text } from 'react-native'
// Wrap user-generated Thai content with explicit break hints
<Text style={{ fontFamily: 'Sarabun', includeFontPadding: false }}>
{text.replace(/(ก-๛)+/g, (m) => m + '')} // zero-width space hint
</Text>
Flutter
Flutter ships its own text rendering pipeline (Skia → Impeller). This means Thai line-breaking is consistent across platforms — same on iOS as Android — but it's also not the platform default. Some Thai users find Flutter Thai text feels "off" because the kerning doesn't match what their OS does elsewhere. Tiny effect, but we've heard it from QA testers in 3 of 4 Flutter projects.
Fonts
For both: ship Sarabun, IBM Plex Sans Thai, or Noto Sans Thai Looped. Don't rely on the system font. Thai system fonts vary wildly between Android OEMs — Samsung, OPPO, Vivo, Xiaomi all ship different defaults. Bundling your own font costs ~200 KB and saves hours of QA.
Axis 5: Performance reality
This is where Flutter advocates and RN advocates fight on Twitter. The actual numbers from our prod apps:
| Metric (median, mid-tier Android) | React Native (Hermes + new arch) | Flutter (Impeller) |
|---|---|---|
| Cold start (ms) | 720 | 520 |
| Scroll FPS, dense list | 56-60 | 58-60 |
| APK size (release) | 14-22 MB | 22-32 MB |
| Bundle update latency (OTA) | ~5 s (EAS Update) | N/A (no native OTA) |
Flutter wins cold-start. RN wins APK size and OTA updates (EAS Update is genuinely transformative — we ship hotfixes in 5 minutes without store review). Scroll performance is a wash in 2026; New Architecture + Hermes closed the gap.
Use case mapping
This is the part you actually want.
Pick React Native (with Expo) when:
- Your team already has React/Next.js engineers (probable if you read our Next.js 15 patterns)
- You need OTA updates for hotfixes or A/B tests
- Your app is content-heavy with frequent server-driven UI changes
- You need a shared codebase with a web product (RN Web is solid; Flutter Web is not)
- You want our 15-day ship timeline (RN's faster on our internal benchmark)
Pick Flutter when:
- Heavy custom animation surface (game-adjacent UIs, fintech with custom charts)
- You need pixel-identical rendering on every device for design QA
- Your designer ships in Material 3 and you'd otherwise rebuild every component in RN
- You have a Dart-fluent team (rare in Bangkok)
Pick native (Swift / Kotlin) when:
- Deep platform integration (HealthKit, ARKit, advanced camera, NFC)
- Performance-critical (real-time audio/video, on-device ML beyond what TFLite offers)
- You're a single-platform product with no plans for the other
Stack we actually ship
For 80% of our mobile briefs, the stack is:
// package.json (Expo SDK 52+)
{
"dependencies": {
"expo": "~52.0.0",
"expo-router": "~4.0.0",
"react": "18.3.1",
"react-native": "0.76.5",
"@shopify/flash-list": "1.7.x",
"nativewind": "4.x",
"zustand": "4.x",
"react-native-mmkv": "2.x",
"react-native-reanimated": "3.x"
}
}
State: zustand + react-query. Storage: mmkv for sync, expo-secure-store for tokens. Styling: nativewind (Tailwind for RN). Navigation: expo-router. Push: expo-notifications + Firebase fallback.
The "but what about React Native Web" question
If you need web + mobile from one codebase, RN Web is real and good. We've shipped 3 in production. The catch: marketing pages still belong on Next.js for SEO reasons (see our Next.js 15 article). The pattern we use is:
- Marketing site, blog, store: Next.js 15 (RSC, server-rendered)
- Authenticated app: Expo + RN Web (single codebase, deployed to
app.example.com) - Mobile binaries: same Expo project, ship via EAS Submit
Hosting for the marketing side: usually Hostinger (see our LiteSpeed performance notes) or Vercel for higher traffic. Migrations off WordPress to this stack are covered in our migration playbook.
What we'd recommend in 2026
Default to Expo + React Native. The hiring pool, OTA updates, ecosystem, and cross-codebase web option win 80% of briefs. Pick Flutter when you have a heavy custom animation surface or a Material-3-everywhere design system. Pick native only when you're hitting a real platform ceiling.
And bundle your Thai fonts. Always.
If you want a 30-minute call to map your specific brief to a stack, email us. We'll tell you honestly which framework matches your team, market, and timeline. We also work with Bangkok Digital on the post-launch CRO and ASO side.
react-native flutter mobile expo thai-market