Most architecture arguments in a young codebase are not worth having.
The CSS framework, the queue, the hosting region, the ORM, even the front-end framework if your boundaries are clean — all of these are replaceable in a sprint or two by a competent team. Arguing about them at kickoff is a way of feeling productive while avoiding the decisions that actually matter.
There are five that behave differently. Get them wrong and you are not refactoring later, you are migrating: coordinated, risky, expensive, and usually at the worst possible moment commercially.
1. Tenancy and the identity model
This is the big one, and it is almost always decided by accident in week one.
How do users, organisations, teams, and permissions relate? Is a user global with memberships, or scoped to one tenant? Can a person belong to two customers? Can permissions be granted on individual resources, or only at role level?
The failure mode is familiar. You build for a single-tenant assumption because your first customers are single organisations. Eighteen months later an enterprise prospect needs sub-organisations with delegated administration, and every query in the codebase needs a tenant boundary it was never written to respect.
Retrofitting multi-tenancy is one of the most expensive migrations in commercial software, because it touches the schema, every query, the cache keys, the background jobs, the exports, the audit trail and the authorisation layer simultaneously — and it must be done without leaking data between customers even once.
You do not need full multi-tenancy on day one. You need a schema where every row that belongs to a customer says so, and an authorisation layer that is consulted rather than assumed.
2. Where the source of truth lives
Every meaningful entity in your system — customer, order, subscription, document — should have exactly one place that owns it.
The alternative is not obviously wrong at first. The CRM has customers, the billing system has customers, the app has customers, and a couple of sync jobs keep them roughly aligned. It works. Then a customer changes their email in one system, a webhook fails silently, and for three weeks two systems disagree about who somebody is.
Reconciliation logic is a tax you pay forever, and it grows superlinearly with the number of systems that think they own the same entity. Decide ownership explicitly, write it down, and make the other systems consumers with a defined refresh path.
3. Data residency and compliance boundaries
Where data physically lives is a schema-level and infrastructure-level decision disguised as a legal one.
If you will ever sell into the EU, into regulated healthcare, or into a public-sector buyer, decide early which data must remain in a region and what crosses the boundary. Retrofitting regional isolation into a system built on one global database means partitioning data, routing requests, splitting backups, and re-establishing every analytics pipeline.
The version of this that catches teams out now is model providers. If your product sends customer content to a hosted inference API, that content has left your boundary, and the answer to where does our data go now includes a third party in a jurisdiction your customer will ask about. Decide it deliberately: what may leave, what must be redacted, what runs in your own boundary, and what you will put in writing during a security review.
4. Integration contracts you expose to others
Internal interfaces can be changed at will. The moment an external party integrates, your API is a promise.
The practical protection is small and cheap at the start: version from the first release, keep the public surface deliberately narrower than your internal model, never let internal enums leak outward, and define a deprecation policy before anyone needs it. Webhooks deserve particular care — at-least-once delivery, idempotency keys, signed payloads, and a documented retry schedule — because consumers build fragile things on top of them and you inherit that fragility.
The instinct to expose your database shape as your API shape is the one to resist. It couples your ability to refactor to somebody else's release schedule.
5. Auditability
Can the system answer, eight months later, who changed what and why?
This looks like a feature request until an enterprise security review, a disputed transaction, or a regulator arrives. Then it is a blocking requirement, and the answer we could add logging is not the same as we have the history.
Bolting audit onto an existing system is hard because the events were never captured. Appending immutable records at the point of change is straightforward when you do it from the start and painful when you do it after. Include actor, action, before and after state, timestamp, and correlation ID — and decide retention consciously rather than by default.
Why this list got more important, not less
The compression of implementation cost by AI assistance has an underappreciated side effect: it is now much faster to build a large amount of code on top of a bad foundational decision.
Generated code fills whatever space you leave it. If the tenancy model is ambiguous, you get ambiguity implemented consistently across two hundred files instead of twenty. If there is no clear source of truth, you get more sync jobs, faster. The speed is real, and it amplifies whatever structure you gave it.
So the useful division of labour is now sharper than it used to be. Spend senior human attention on the five decisions above and on the boundaries between components. Let tooling accelerate the work inside those boundaries, where mistakes are cheap and local.
A short checklist for kickoff week
- Every customer-owned row carries its tenant. Authorisation is consulted, never assumed.
- Each core entity has one named owning system, written down.
- Data residency and what leaves the boundary — including to model providers — is decided and documented.
- Public API is versioned, narrower than the internal model, with a deprecation policy.
- Audit events are emitted at the point of change with actor, before, after and correlation ID.
Everything else can wait until you have evidence.
The full buyer-side version of this — engagement models, budgets, contract terms and evaluation questions — is on our blog: Product Development Services: A 2026 Buyer's Guide for CTOs. More on how we approach custom software development.
Frequently Asked Questions
Which architecture decisions are actually hard to reverse?
Tenancy and identity modelling, the source of truth for each core entity, data residency and compliance boundaries, externally exposed API contracts, and auditability. Nearly everything else — frameworks, queues, hosting choices — is replaceable by a competent team within a sprint or two.
Do I need multi-tenancy from day one?
Not full multi-tenancy, but you do need a schema where every customer-owned row carries its tenant and an authorisation layer that is consulted rather than assumed. Those two habits keep the door open cheaply; retrofitting them later touches queries, caches, jobs, exports and the audit trail at once.
How do I decide the source of truth across multiple systems?
Pick one owning system per entity, write it down, and make every other system a consumer with a defined refresh path. Bidirectional sync between two systems that both believe they own the same record produces reconciliation work that grows with every additional system.
What does data residency mean for AI features?
If customer content is sent to a hosted inference provider, it has left your compliance boundary and a security reviewer will ask about it. Decide explicitly what may leave, what must be redacted, what runs inside your own boundary, and be able to put that answer in writing.
When should I version a public API?
From the first external consumer. Keep the public surface narrower than your internal model, avoid leaking internal enums, and publish a deprecation policy before you need one — otherwise your ability to refactor becomes dependent on someone else's release schedule.
Does AI-assisted coding change how much architecture matters?
It raises the stakes. Generated code fills whatever structure you provide, so an ambiguous foundational decision gets implemented consistently across far more files than it used to. Spend senior attention on boundaries and the five irreversible decisions; let tooling accelerate work inside them.


Top comments (0)