Imagine: you have a site for Russia (company.ru), for Kazakhstan (company.kz), and for Belarus (company.by). Each must display its own prices, content, and legal information. But maintaining three separate sites is expensive and inefficient. The solution is a multidomain site on a single codebase, built on the principles of multitenancy. We set up such systems turnkey, ensuring full content isolation and maximum local SEO signal. A multidomain is 2–3 times stronger than subdirectories in local SEO signal strength, as confirmed by our clients' cases (traffic increase up to 30%).
Problems solved by a multidomain
Separating content and settings — configuring a multidomain site
Each domain is an independent site in Google's eyes. This requires different currency, timezone, legal texts, and prices. A single database with domain binding solves the problem without code duplication. We use a site_domains table storing host, country code, locale, and currency. This approach saves up to 40% of update time compared to maintaining separate installations.
SEO isolation and hreflang
Google must see that company.kz and company.ru are different sites for different countries. For this, we generate hreflang tags in the head of each page. An error in hreflang leads to penalization — we exclude this by automatic generation based on the domain table. Proper configuration increases local organic traffic by an average of 30%.
Session loss when switching between domains
Note: when a user navigates from company.ru to company.kz, the session is lost — cookies are not passed between different domains. We implement SSO via a one-time token: when clicking "Go to site for Kazakhstan", a token is generated, the second domain exchanges it for a session. This works without shared cookies and does not require a single domain.
How multitenant architecture works?
At the core is the site_domains table linking the domain to settings. Middleware ResolveSiteDomain determines the current domain, sets locale, timezone, and currency. Content is stored with domain binding — specific pages override common ones.
CREATE TABLE site_domains ( id SERIAL PRIMARY KEY, host VARCHAR(253) UNIQUE NOT NULL, country_code CHAR(2) NOT NULL, locale VARCHAR(10) NOT NULL, currency CHAR(3) NOT NULL, timezone VARCHAR(64) NOT NULL, is_primary BOOLEAN DEFAULT false, is_active BOOLEAN DEFAULT true, meta JSONB DEFAULT '{}' ); Middleware for domain resolution
class ResolveSiteDomain { public function handle(Request $request, Closure $next): Response { $host = $request->getHost(); $domain = SiteDomain::where('host', $host)->where('is_active', true)->first(); if (!$domain) { $primary = SiteDomain::where('is_primary', true)->firstOrFail(); return redirect("https://{$primary->host}" . $request->getRequestUri(), 301); } app()->instance('site.domain', $domain); App::setLocale($domain->locale); Carbon::setlocale($domain->locale); date_default_timezone_set($domain->timezone); return $next($request); } } Nginx: virtual hosts
A single server block with multiple server_name is sufficient. SSL certificates can be combined into SAN or use a wildcard.
server { listen 443 ssl http2; server_name company.ru company.kz company.by; ssl_certificate /etc/letsencrypt/live/company.ru/fullchain.pem; root /var/www/company/public; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param HTTP_HOST $host; include fastcgi_params; } } Generating hreflang
A helper generates tags for all active domains:
function hreflangTags(string $path): string { $domains = SiteDomain::where('is_active', true)->get(); return $domains->map(fn($d) => "<link rel=\"alternate\" hreflang=\"{$d->locale}-{$d->country_code}\" href=\"https://{$d->host}{$path}\" />" )->join("\n"); } What multidomain gives compared to subdirectories?
| Characteristic | Multidomain | Subdirectories |
|---|---|---|
| Local SEO signal strength | High (separate domain) | Medium (subdomain or folder) |
| Content isolation | Full: different legal requirements, currencies | Limited: shared domain, harder to make different versions |
| SSL management | Requires SAN or wildcard certificate | One certificate for the whole domain |
| Implementation complexity | Higher: middleware, SSO, hreflang | Lower: just subdirectories |
| Maintenance | One codebase | One codebase |
How to add a new domain?
- Register the domain and configure DNS A records (up to 24 hours for propagation).
- Add a record to the
site_domainstable — 2 minutes. - Update the SAN certificate via Certbot — 5 minutes.
- Add server_name to Nginx and reload — 1 minute.
- Import or create content for the new domain (depends on volume).
The whole procedure takes about an hour, not counting DNS time.
Google Search Central recommends choosing between multidomains and subdirectories based on business requirements. Multidomain is preferable when content and brand differ greatly across countries.
Common mistakes and how to avoid them
- Forgetting fallback content. If a page is not found for a specific domain, it should be loaded from the common pool, otherwise the user will see a 404. We implement this via a global route provider.
- Incorrect initialization order. Locale and timezone must be set before any Eloquent query is called — at the middleware level.
- Ignoring caching. For a multidomain site, the cache must be partitioned by domain (via prefix or separate tag), otherwise a user from one domain will see a cached page from another.
Work stages
| Stage | Description | Duration (days) |
|---|---|---|
| Audit | Analyze current architecture, choose strategy | 1 |
| Design | DB schema, domain table, routing | 1 |
| Implementation | Middleware, provider, helpers, content migration | 2–3 |
| Testing | Verify hreflang, sessions, caching | 1 |
| Deployment | Configure Nginx, SSL, DNS | 1 |
Total: 2–5 days.
Deadlines and cost
Our engineers have 5+ years of experience in building multitenant systems and have implemented over 50 multidomain projects. A typical multidomain setup project takes from 2 to 5 business days depending on the complexity of the existing code and the volume of content. The cost is calculated individually after an audit — order an audit of your current architecture or get a consultation. We guarantee correct hreflang configuration and complete SEO isolation.







