If you've reached for acts_as_tenant or apartment without really understanding what's happening underneath, this tutorial is the correction. We're building a row-level multitenant system from first principles — the kind you can actually reason about when something goes wrong at 2am.
By the end, you'll have:
Middleware that resolves the current tenant from a subdomain or JWT claim
A Current -based tenant context that threads safely through the request lifecycle
An ApplicationRecord mixin that enforces tenant scoping at the model layer
Postgres row-level security policies as a hard backstop
A TenantSafe concern for background jobs that re-establishes context correctly
A test helper that won't let you accidentally write cross-tenant specs
No gems. Just Rails, Postgres, and honest code.
The Mental Model
Row-level multitenancy means every tenant's data lives in the same tables , separated by a tenant_id foreign key. The application layer is responsible for filtering.…