Multi-tenant SaaS építés MVP-ből — 6 hiba, amit nem szabad elkövetni
Minden SaaS, amit elindítasz, előbb-utóbb multi-tenant lesz. A kérdés csak az, hogy te tervezed-e be, vagy a 7. ügyféled fogja kikényszeríteni egy late-night incidentben. Hat hiba, amit mi vagy az ügyfeleink elkövettünk, és amitől szeretnénk megóvni.
1. tenant_id elfelejtése egy táblán
Az alapszabály: MINDEN üzleti tábla első oszlopa tenant_id. Még a tags is. Még a user_preferences is. A legkisebb kivétel is megbosszulja magát — egy ügyfél nálunk 14 hónap múlva fedezte fel, hogy az email_templates táblán nincs tenant_id, és a B-tenant által mentett sablon megjelent az A-tenant fiókjában.
Kényszerítsd ki migration-szinten: ne legyen tábla tenant_id nélkül, kivéve nyíltan közöset (pl. tenants, tenant_billing_plans).
2. Row-level security (RLS) nélkül indulás
„Majd a service layer ellenőrzi.” Nem fogja. Egyetlen elfelejtett WHERE egy admin-eszközben, egyetlen rosszul scope-olt JOIN, és az adat keresztbe folyik. Postgres RLS bekapcsolása nem opcionális — az MVP első hetén megy be.
Mért adat egy 2026-os ügyfél-audithoz: 17 service-réteg lekérdezésből 3 nem szűrt tenant_id-ra. RLS-sel ezek hibára futnak, anélkül észrevétlenül szivárogtak volna.
3. Túl korai sharding
A „skálázni fogunk” narratíva ellenére: az első 200 tenantig egyetlen Postgres elég. A sharding-tax (cross-shard JOIN, eventual consistency, devops bonyolítás) most több költség, mint amennyi haszon. Tedd be a shard-key oszlopot (shard_key), tedd be a tenant→shard mapping táblát — de maradj egy shardon addig, amíg a p99 > 500ms vagy a DB-CPU > 70% nem tartós.
4. Közös sequence per tenant
A quote_number és társai: ha SERIAL-t használsz egyetlen sequence-szel, B-tenant ajánlatszámai ugranak A-tenant ajánlatszámai miatt. Ez nemcsak csúnya — könyvelési problémát is szül.
Minta: (tenant_id, sequence_id) kompozit, INSERT ... RETURNING egy per-tenant nextval('tenant_X_quotes_seq')-ből, vagy explicit tenant_counters tábla FOR UPDATE-tel. Egyszerű, és mindkét fél hálás.
5. Hard-coded subdomain
„Egyelőre acme.app.example.com alá tesszük az Acme-t.” Hat hónap múlva: 47 subdomain, Cloudflare DNS-szabály karbantarthatatlan, SSL-cert-rotation egy rémálom. Ráadásul az új ügyfél már a saját domainjén akarja látni a SaaS-t (portal.acme.com).
Kezdettől fogva: Host-header alapú tenant resolution. A subdomain csak egy kényelmi alias. Az adatbázisban a tenant „host_aliases” mező egy listát tárol (acme.com, portal.acme.com, acme.app.example.com). Egy ingress, egy wildcard cert, sok host.
6. Közös search index
Elasticsearch / Meilisearch / OpenSearch: ha az egész SaaS egyetlen indexre keres, a tenant_id filter csak query-time. A query-tervező drága lesz, a re-index egy tenantre az egész indexet érinti, és egy konfig-hiba megint adatszivárgáshoz vezethet. Tenant-per-index (vagy legalább per-index-alias) — kicsit drágább storage, sokkal egyszerűbb biztonság.
A tanulság
A multi-tenant nem egy „kapcsoló, amit később felcsapunk”. Architektúra-réteg, és az MVP első napján kell beletervezned. A fenti hat hiba mindegyike újraírást kíván a 18. hónapban — kivéve, ha az 1. hónapban már jól csináltad.