RGCS
← Blog
SaaSTypeScriptPostgreSQLBackend

Why I Reach for Encore.dev on Multi-Tenant SaaS Projects

When I started building RestaurantOS Encore, I had the usual options in front of me: raw Express, NestJS, or something serverless. I chose Encore.dev and haven't looked back. Here's an honest account of why.

The problem with rolling your own infrastructure

Every backend I've built from scratch has the same invisible tax: 30–40% of early work goes to scaffolding that has nothing to do with the product. Auth middleware, environment configs, database connection pooling, service-to-service calls that need to stay type-safe. You set it up, it works, and you never think about it again — until it breaks at 2am.

Encore flips the model. You write TypeScript, you decorate functions with api(), and infrastructure is inferred. The framework generates Terraform, sets up queues, wires services together. Your code is the config.

PostgreSQL Row Level Security — the right way to do multi-tenancy

The piece that sold me was native RLS integration. Multi-tenant SaaS has exactly one hard problem: making sure tenant A can't see tenant B's data. The solutions are:

  1. Separate databases per tenant — clean, expensive to operate at scale
  2. Application-layer filteringWHERE tenant_id = ? everywhere, easy to forget one
  3. Row Level Security in Postgres — policy enforced in the database engine, unforgeable

Encore makes option 3 trivial. You declare the database, write your RLS policies, and the framework passes the session context through automatically. I don't have to remember to filter — the database rejects queries that violate policy.

For a POS system handling real money and real orders, that guarantee matters.

Two-tier auth without ceremony

RestaurantOS needed two classes of user: managers (who set up the system) and employees (who take orders at the terminal). Different permissions, different UX, different trust levels.

With Encore's auth middleware, I defined two handlers. Manager auth issues JWTs with a role: manager claim. Employee auth validates 4-digit PINs against bcrypt hashes and issues short-lived tokens scoped to a single location. The auth layer runs before any endpoint handler — no decorators to forget, no middleware order to get wrong.

What I'd warn you about

Encore isn't free of trade-offs. The CLI toolchain is opinionated, and if you want to reach outside the Encore ecosystem (say, a custom Docker layer or a specific Postgres extension), you'll fight the framework. The local dev experience is excellent; production deploys to Encore Cloud or self-hosted GCP/AWS work well, but the self-hosted path has more surface area than a typical docker compose up.

I also wouldn't use Encore for simple CRUD APIs. The abstraction pays off when you have multiple services that need to communicate, shared infrastructure like queues and caches, and security requirements that need to be system-wide. For a single-service REST API, it's overkill.

The verdict

If you're building a genuine multi-tenant SaaS product in TypeScript — one with multiple services, real auth requirements, and Postgres as the store — Encore is the fastest path from idea to production I've found. The RLS integration alone is worth the learning curve.

RestaurantOS Encore handles POS, KDS, and staff management as separate Encore services sharing a tenant-scoped database. The whole thing runs locally with a single encore run, and the production infra is generated, not hand-written. That's the trade I'll take every time.

RG

RGCS

Vancouver-based software & AI studio