SaaS
SaaS architecture that you can still change in year three
The first version of a SaaS product is allowed to be small. It is not allowed to be vague. Vague tenancy, informal permissions, and “we will add billing later” produce a codebase that every new customer makes worse. You do not need a platform team. You do need a few decisions that you can explain on a whiteboard.
Tenancy should be a constraint, not a convention
If tenant data is isolated only because every query happens to include tenant_id, it will leak. Put the constraint where it cannot be forgotten: a global scope, a connection, or a schema strategy you actually understand. Then write a test that fails if a request can read another tenant’s records. That test is cheaper than the incident.
Billing is a boundary
Plans should gate expensive or sensitive capabilities, not rename buttons. Keep Stripe (or your processor) at the edge. Your domain should know “this workspace is on the growth plan until this date,” not the raw webhook payload. Failed payments need a path that does not require an engineer to interpret a dashboard.
Build the admin you will pretend you do not need
Someone will need to disable a user, inspect a tenant, and refund a charge. If that work requires production access, you do not have an admin tool — you have a ritual. A modest internal application with an audit log is part of the product, even if customers never see it.
Leave room, not imaginary scale
You probably do not need microservices, event sourcing, or a custom queue protocol. You do need background jobs, a migration habit, and the discipline to keep domain logic out of controllers. Maintainable SaaS is usually a modular monolith that a small team can still run.
If you are making a similar decision on a product or internal system, tell us about the workflow. Related reading lives with our services.