Shared schema, enforced isolation
One Postgres database with a tenant_id on every row and isolation enforced by row-level security policies at the database layer, not in application code. A missed WHERE clause in a query cannot leak another company's data, because the database itself refuses to return it.
Tenant provisioning as a product feature
New-company onboarding became a form, not a project: company record, subdomain, branding, seat limits, a Moyasar payment profile, and a Wafeq invoicing account created in one transaction. Setup that previously took weeks of manual work now completes in under a day, most of it waiting on the customer's own data import.
Billing that matches the plan
Per-seat subscription billing with proration and dunning collected through Moyasar, the Saudi payment gateway, with invoices issued through Wafeq and reconciled nightly against the tenant registry so finance and the database never disagree about who pays for what.
Per-tenant branding and domain handling
Each tenant gets its own subdomain, logo, and color scheme resolved at the edge from the hostname, before application code runs. A dispatcher at acme.app and one at globex.app see two different products that happen to share one deployment.
Operated by two, not twenty
Migrations run automatically on deploy, and background workers handle everything that must not block a dispatcher's request: subscription charges, dunning retries, and the nightly reconciliation that compares the tenant registry against Moyasar and Wafeq. Alerting ships to the small internal team. The architecture assumes no on-call rotation exists, because for this client it does not.