Subdomain Multi-Region Setup for Bilingual Sites

Run en.yoursite.com and zh.yoursite.com on separate hosting regions to cut TTFB for each audience — without splitting SEO or breaking shared assets. Verified June 2026.

Running a bilingual site from a single hosting region means one audience always sees the slow version. If your origin sits in us-central1 (Iowa), a reader in Shanghai waits for the first byte to cross the Pacific before any CDN can help. Putting each language on its own subdomain pointed at the closest region — en.yoursite.com in the US or EU, zh.yoursite.com in Hong Kong, Singapore, or Tokyo — moves the origin next to each audience. Done right it trims 200-400 ms of TTFB for the far-side language without splitting SEO or breaking shared assets.

TL;DR

  • Split by language subdomain only if your two audiences sit on different continents and your analytics shows lopsided TTFB. Otherwise stay on language-prefix paths (/en/, /zh/) — they are simpler and SEO-equivalent.
  • Pure static hosts (Cloudflare Pages, Vercel, Netlify) already serve from a global CDN, so the win is small. The split pays off when you have a single-region origin — Firebase Hosting/App Hosting, App Engine, Render, fly.io.
  • Each subdomain needs its own deploy target, SSL cert, sitemap, and a self-referencing canonical. hreflang must be reciprocal across both subdomains or Google ignores the whole cluster.
  • For mainland-China readers, hosting in Hong Kong or Singapore does not bypass the Great Firewall. Traffic still crosses it, adding roughly 2x latency and 5x packet loss versus a HK-local request. A truly fast China experience needs mainland hosting plus an ICP filing — a much bigger commitment.

When the split is worth it

Reach for this only when the symptoms are clear:

  • Analytics shows TTFB above 800 ms for the language whose audience lives on the opposite side of the planet from your origin.
  • You ship the same content in two languages, but only one region’s users complain about speed.
  • You already use language-prefix URLs and SEO is fine — performance is the only thing that is uneven.
  • Your bill shows most traffic egressing through one region while the other sits idle.

If you are on a global-CDN static host like Cloudflare Pages (300+ edge locations as of June 2026) or Vercel (~30 regions), your HTML is already cached near both audiences and a region split buys you little. The split matters when you have a single fixed origin and dynamic responses that cannot be edge-cached.

DNS and hosting layout

Each subdomain is its own deploy target on its own region. The DNS records look like this:

en.yoursite.com    CNAME    cname.vercel-dns.com          # US/EU region
zh.yoursite.com    CNAME    yoursite-zh.web.app           # asia-east1 (Taiwan)
yoursite.com       A        76.76.21.21                   # 301 to a default
www.yoursite.com   CNAME    cname.vercel-dns.com          # mirrors en. or redirects

The bare domain and www should 301-redirect to one language subdomain based on Accept-Language, or to a tiny language-picker page. Do not serve content from the bare domain in parallel with the subdomains — that creates a third URL family competing for the same content and diluting every signal.

Canonical and hreflang across subdomains

This is where most teams get it wrong, and the cost is brutal: a single broken return tag makes Google drop the entire hreflang cluster. Studies put the error rate around 75%, and missing return tags are the most common cause. Each page on en.yoursite.com/articles/foo/ declares a self-referencing canonical AND hreflang alternates pointing to its zh counterpart:

<link rel="canonical" href="https://en.yoursite.com/articles/foo/">
<link rel="alternate" hreflang="en" href="https://en.yoursite.com/articles/foo/">
<link rel="alternate" hreflang="zh" href="https://zh.yoursite.com/articles/foo/">
<link rel="alternate" hreflang="x-default" href="https://en.yoursite.com/articles/foo/">

The zh page mirrors the structure, with its own self-canonical to the zh.yoursite.com URL and the same set of alternates. Both subdomains must list each other — one-way hreflang is ignored. Per Google’s own docs, subdomains and language-prefix paths are equally valid for hreflang; the choice is purely operational (DNS, hosting, analytics), not an SEO ranking factor. So do not split for SEO reasons. Split for latency, and keep the SEO neutral.

Shared assets — pick one CDN origin

If you serve fonts, images, or JS bundles from both subdomains, two patterns work:

  1. Each subdomain keeps its own copy. Simpler, more duplication, fine for small bundles.
  2. One shared asset subdomain (cdn.yoursite.com) with CORS configured. Both en and zh load from it, sharing one cache across both audiences at the cost of one extra DNS lookup on first load.

Pick option 1 if total assets are under ~500 KB. Pick option 2 if you have larger bundles, custom fonts, or want a single cache shared across both languages. Either way, host that CDN origin on a global edge network (Cloudflare R2 + Pages, or Vercel’s CDN) so neither audience pays a cross-ocean penalty for assets.

Verifying the latency win

Setting all this up is real work. Verify before you celebrate. Use WebPageTest or Pingdom to load each subdomain from at least three vantage points that match your audience: a US city, a Chinese city, and one neutral third (Singapore is a good neutral anchor).

Watch two numbers: TTFB (origin response time) and total document load. If zh.yoursite.com from Shanghai now measures ~200 ms TTFB instead of the old ~700 ms US-only path, the migration worked. If the numbers barely move, your “Asia” region is likely misconfigured — Firebase asia-east1 is in Taiwan, not mainland China, and a Beijing reader’s packets still traverse the Great Firewall. Independent measurements show the Firewall’s filtering alone slows delivery into China by up to 40%, and China-to-Hong-Kong traffic carries roughly 2x the latency and 5x the packet loss of a HK-local request. Compare a Singapore region or HK CDN edge before declaring the project done — and set expectations honestly with anyone who promised “fast in China.”

Deploy workflow with two regions

The cleanest workflow keeps a single source of truth and ships to two targets. One build, with a regions.json (or a per-deploy environment variable) selecting the public origin URL and the closest region:

# CI: build once, deploy to each region target
npm run build
firebase deploy --only hosting:en --project en-us
firebase deploy --only hosting:zh --project zh-asia

Firebase App Hosting now lets each backend pin a region directly (firebase apphosting:backends:create --location asia-east1), so you no longer need two whole projects just to split regions — two backends in one project works.

Plan for two failure modes. First, one region succeeds and the other fails. Set CI to abort and roll back when either deploy fails, or you will ship a half-deployed site for hours. Second, both succeed but at different times, so users on the lagging region briefly see old content. That is acceptable for a content site, painful for an app — for apps, pin both regions to the same Git SHA and verify both before flipping any feature flag.

Common mistakes

  • Forgetting SSL on the second subdomain. The site loads but the browser warns about an insecure connection. Most hosts auto-provision per custom domain; confirm the cert issued before you announce the new subdomain.
  • Asymmetric hreflang. en lists zh but zh does not list en. Google ignores the whole cluster, not just the broken link.
  • Canonicalizing both languages to one subdomain (usually en). Google deindexes the other language entirely.
  • Search Console set up wrong. A Domain property covers every subdomain at once; a URL-prefix property covers only one. If you used URL-prefix, add en. and zh. as separate properties or half your indexing data is invisible.
  • Sitemaps referencing one subdomain. Each subdomain needs its own sitemap listing only its own URLs.
  • Cookie/session domain set to one subdomain instead of .yoursite.com. A user logged in on en. is logged out the moment they switch to zh..

FAQ

  • Should I use /en/ paths instead of subdomains?: Path-based is simpler — one Search Console Domain property, one SSL cert, one deploy — and Google treats it as SEO-equivalent. The one thing it cannot do is give you per-region origins. If origin latency is your real problem, use subdomains; otherwise stay on paths.
  • Will Google treat the subdomains as separate sites?: Somewhat. Each subdomain accumulates its own authority and, with URL-prefix properties, needs its own Search Console entry (a Domain property covers both). Internal links between them help but are not as tightly coupled as same-domain paths.
  • Does hosting in Hong Kong or Singapore make my site fast in mainland China?: Not really. Traffic from China to HK/SG still crosses the Great Firewall, which adds latency, packet loss, and filtering delays of up to ~40%. Only mainland hosting truly avoids the crossing — and that requires an ICP filing, which a foreign owner can only obtain through an onshore entity (WFOE or local partner). Plan 2-4 weeks minimum.
  • What about a ccTLD (.cn, .com.cn) instead of zh.?: A ccTLD sends the strongest geo-targeting signal but requires separate domain ownership, ICP registration, and roughly double the ongoing cost. For most indie devs, a subdomain is the cheaper starting point.
  • Can I run two regions per language on the same host?: On Firebase, deploy two Hosting sites (or two App Hosting backends), each pinned to its own region. On Vercel, create two projects, point each at its subdomain, and rely on Vercel’s CDN for edge caching.
  • Do I need a separate analytics property per subdomain?: Use one property with cross-subdomain tracking configured, so a reader who switches from en. to zh. stays in the same session instead of registering as a new visit.

Tags: #Indie dev #Domain #DNS #multi-region #Bilingual