How does Remix handle multi-tenant applications?

Answer

Multi-tenant Remix applications use several patterns. Subdomain-based tenancy: resolve tenant from subdomain in the root loader: const host = request.headers.get("Host"); const subdomain = host?.split(".")[0]; const tenant = await db.getTenant(subdomain); if (!tenant) throw new Response("Not Found", { status: 404 }); return json({ tenant });. Share tenant context via React context or use Remix's loader data in child routes. URL path-based tenancy: routes/$tenant/ — the tenant is a route parameter available in all nested loaders. Database isolation: row-level security (add tenant_id to all queries), separate schemas (Postgres search_path), or separate databases per tenant. Caching: Remix uses HTTP cache headers — include tenant identifier in Vary header or cache key. Shared components: use useFetcher to avoid full navigations when switching tenants. Authentication: tenant-scoped sessions — session data includes tenant ID, verified in every protected loader. The root layout loader is the ideal place to resolve and cache tenant context for all child routes.