Running a bilingual site from a single hosting region means one audience always sees the slow version. The fix is to put each language on its own subdomain pointed at the closest region — en.yoursite.com in the US, zh.yoursite.com in Hong Kong or Singapore. Done well it cuts TTFB by 200-400ms for half your users without splitting SEO or breaking shared assets.
Background
Most static-site hosts (Vercel, Netlify, Cloudflare Pages) auto-distribute via global CDN. Most app hosts (Firebase, App Engine, fly.io, Render) pick one origin region and serve from there. If your origin is us-central1 and a Chinese user fetches HTML, the first byte takes 400ms before any CDN can help. Splitting subdomains by region puts the origin close to each audience. The trade-off is more moving parts: two deploys, two SSL certs, two sets of DNS records.
How to tell
- Your analytics shows TTFB above 800ms for the language whose audience is 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 (
/en/,/zh/) and SEO-wise they work, but performance is uneven. - Your hosting bill shows most traffic egressing through one region while the other sits idle.
Quick verdict
For bilingual sites with audiences on different continents, use en.yoursite.com pointed at a US/EU region and zh.yoursite.com pointed at HK/SG/Tokyo. Keep canonical and hreflang consistent so SEO treats them as language alternates. Share build artifacts where possible. The 200-400ms latency win is real for the language whose audience is far from your default region.
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 cname.firebaseapp.com # asia-east1 region
yoursite.com A 76.76.21.21 # redirects to a default
www.yoursite.com CNAME cname.vercel-dns.com # mirrors en. or redirects
The bare domain and www typically 301-redirect to one of the language subdomains based on Accept-Language, or to a tiny language picker page. Do not serve content from the bare domain in parallel with the subdomains — it creates a third URL family that competes for the same content.
Canonical and hreflang across subdomains
This is where most teams get it wrong. 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 hreflang alternates pointing in both directions. Both subdomains must list each other’s URLs — one-way hreflang is ignored.
Shared assets — pick one CDN origin
If you serve fonts, images, or JS bundles from both subdomains, two patterns work:
- Each subdomain has its own copy. Simpler, more duplication, fine for small bundles.
- One shared asset subdomain (e.g.
cdn.yoursite.com) hosting the assets, with CORS configured. Bothenandzhload fromcdn. Saves cache hits at the cost of one extra DNS lookup on first page load.
Pick 1 if total assets are under 500 KB. Pick 2 if you have larger bundles, custom fonts, or want one cache shared across both audiences.
Verifying the latency win
Setting all this up is a lot of work. Verify the win before you celebrate. Use a tool like WebPageTest or Pingdom to load each subdomain from at least three locations matching your audience: a US city, a Chinese city, and one neutral third (Singapore is a good neutral point).
The numbers to watch are TTFB (origin response time) and total document load. If zh.yoursite.com from Shanghai measures 200ms TTFB instead of the old 700ms from the US-only setup, the migration worked. If the numbers are roughly the same, your “Asia” region is misconfigured — Firebase asia-east1 is in Taiwan, not in mainland China, and a Beijing-based user may still take a long path. Compare a Singapore region or HK CDN edge before declaring the project complete.
Deploy workflow with two regions
The cleanest deploy workflow keeps a single source of truth and ships to two targets. Your repo has one build, but a regions.json (or environment variable per deploy) chooses 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
Two failure modes to plan for. First, one region succeeds and the other does not — set CI to abort and rollback when either fails, or you ship a half-deployed site for hours. Second, both regions succeed but at different times; users on the lagging region see old content. Acceptable for a content site, painful for an app — for apps, pin both regions to the same Git SHA and verify before flipping a feature flag.
Common mistakes
- Forgetting to configure SSL for the second subdomain. The site loads but warns about insecure connection.
- Mismatched
hreflang—enlistszhbutzhdoes not listen. Google ignores the asymmetric setup. - Canonicalizing both language subdomains to one (usually
en). Google deindexes the other language. - Running two separate Search Console properties without verifying both — half the indexing data invisible.
- Letting sitemaps reference only one subdomain. Each subdomain needs its own sitemap listing only its URLs.
- Cookie or session-token domain set to a single subdomain instead of
.yoursite.com— users logged in onenare logged out when they switch tozh.
FAQ
- Should I use
/en/paths instead of subdomains?: Path-based is simpler (one Search Console property, one SSL cert, one deploy) but cannot give you per-region origins. If latency matters more than simplicity, use subdomains. - Will Google treat subdomains as separate sites?: Yes, somewhat. Each subdomain needs its own Search Console property and accumulates its own authority. Internal links between them help, but they are not as tightly linked as same-domain paths.
- What about
ccTLD(.cn,.com.cn) instead ofzh.?: ccTLDs send the strongest geo-targeting signal but require separate domain ownership, ICP registration in China, and double the cost. For most indie devs, subdomains are the cheaper start. - Can I run the same hosting setup with different regions per language?: On Firebase: deploy to two different Hosting sites, each with its own functions region. On Vercel: deploy two projects with the build command, point each project at its subdomain.
- Do I need a separate analytics property per subdomain?: Same property, but configure cross-subdomain tracking so a user switching from
en.tozh.stays in the same session.