What multi-tenant means in practice
Multi-tenancy means multiple adventure tourism operators use the same application, each with their own data, users and configurations, with no possibility of data mixing.
There are three main models: database per tenant, schema per tenant, and shared database with a tenant_id column. We chose the third, which has the most traps.
The forgotten tenant_id problem
With the shared database model, the main risk is forgetting to filter by tenant_id in some query. In an application with dozens of models and hundreds of queries, this happens. And when it happens in production, one operator sees another's data.
The solution was a Prisma helper that wraps the client and automatically adds the tenant filter to all operations.
Row Level Security as a second defense layer
In addition to application-level filtering, we implemented Row Level Security (RLS) in PostgreSQL. Even if a bug in the application code omits the tenant_id filter, the database rejects access to other tenants' rows.
Coolify as SaaS deployment platform
OmniTrip runs on Coolify on a Hetzner VPS. The deployment workflow: push to main triggers a webhook, Coolify pulls the repository, runs docker build, runs prisma migrate deploy as part of the entrypoint, and does a rolling restart.
What I'd change today
Today I'd use Prisma Client Extensions for tenant isolation instead of the manual helper. Extensions let you extend the client with custom logic in a more type-safe, error-resistant way.
