The biggest architectural challenges for an ISV moving from single-tenant to multi-tenant SaaS are customer-specific customisations, the data model (keys, schema drift and per-tenant uniqueness), tenant identity, configuration, and a rollout that can be reversed. The code change is usually smaller than the migration of live customers.
This guide is for independent software vendors (ISVs) that already run one installation per customer and want a single shared platform. It is about the move itself: what breaks, in what order, and how to keep every customer safe while it happens. It does not repeat the comparison of tenancy models in our multi-tenant SaaS architecture guide, or the list of single-tenant assumptions to remove from internal software in turning internal software into a SaaS product. If you want a team to plan and build the move, see our SaaS development company page.
Key takeaways
- Treat the migration of live customers as the project, and the shared-platform code as a prerequisite.
- Per-customer databases drift. Audit every install's schema before you design the shared one.
- Integer IDs collide when databases merge. Decide on composite keys, new IDs with a mapping table, or UUIDs, and keep the old ID for support and reconciliation.
- Customisations need triage: configuration, extension point, metadata-driven custom fields, a dedicated tier, or retire.
- Run the multi-tenant code with a single tenant on existing installs first, then move customers in waves.
- Define a point of no return for each customer, and keep the old install read-only until the agreed period ends.
Why is the move harder than the code change suggests?
Adding a tenant key to the code is a finite task. Moving forty customers, each with their own data, settings, integrations and promises, into one platform without losing a record is the part that fails. The risk sits in the differences between installs, not in the product itself.
Single-tenant estates drift. One customer is two releases behind, another has a hand-edited column, a third has a scheduled job nobody remembers. Before any design, build an inventory per install: release version, schema differences against your canonical schema, custom code, integrations, data volume, contractual isolation promises, and the person who owns the relationship. That inventory sets the order of migration and shows which customers will never fit the shared model.
What changes in the data model?
The data model changes in four places: every row gets a tenant key, identifiers must stay unique after merging, uniqueness rules become per-tenant, and schema differences between installs must be resolved into one canonical schema. Get these decisions made before writing migration scripts.
| Decision | Options | Trade-off |
|---|
| Identifiers when merging databases | Composite key (tenant_id, id); new IDs plus a mapping table; UUIDs generated for all rows | Composite keys are simple but touch every foreign key. New IDs need a careful remap order. UUIDs avoid collisions later but change every reference, and random UUIDs can hurt index locality on large tables (time-ordered ones avoid that). |
| Original IDs | Keep as a legacy_id column | Lets support and customers trace a record back to the old system and makes reconciliation possible. |
| Uniqueness | Unique within a tenant, not globally | Customer codes, invoice numbers and usernames must be re-scoped, with their own sequence per tenant. |
| Schema drift | Diff every install against the canonical schema; decide per difference | Extra columns either become custom fields, are dropped with the customer's agreement, or keep the customer on a dedicated tier. |
| Enforcement of the boundary | Database policies (for example PostgreSQL row-level security) plus a data-access layer that refuses unscoped queries | Relying on every developer to remember a filter will eventually fail. If you use row-level security, check your database documentation: in PostgreSQL, for example, table owners (unless the table uses FORCE ROW LEVEL SECURITY), superusers and roles with BYPASSRLS skip the policies. Run the application as a role that cannot bypass them, and set the tenant on every connection checkout. |
Also search for everything outside the database that carries data: file storage paths, caches, search indexes, report outputs, background job payloads and logs. Each needs the tenant identifier, or one customer's document can be served to another.
How should tenant identity work after the move?
Tenant identity means the platform always knows which tenant a request belongs to, resolved on the server and then checked against the signed-in user, never taken on trust from a value the browser can edit. Users may belong to several tenants, each tenant may bring its own single sign-on, and API keys must be scoped to one tenant.
- Resolve the tenant on the server. From the signed-in session, or from a subdomain or custom domain that you map to a tenant. Never trust a header or parameter alone: after resolving the tenant, check that the signed-in user is a member of it.
- Separate the user from the membership. In single-tenant systems a user belongs to the install. In a shared platform one person (a consultant, an auditor) may need access to several tenants, so model users and tenant memberships separately.
- Per-tenant single sign-on. Enterprise customers expect to connect their own identity provider, typically through SAML or OpenID Connect. Plan the sign-in service as shared infrastructure, with a tenant-specific configuration.
- Scope machine access. API keys, webhooks and integration credentials belong to one tenant and are stored and rotated per tenant.
- Support access. Replace shared admin logins with time-limited, logged access that the customer's own administrator can see.
How do you handle configuration across tenants?
Configuration is everything that differs per customer but is not code: currency, time zone, numbering, branding, workflow rules, limits and feature switches. In a shared platform it lives in data, in layers (platform defaults, plan defaults, tenant overrides), so a customer change never requires a deployment.
Single-tenant products often hide configuration in config files, environment variables and code branches that test the customer's name. Find these by searching for customer names and identifiers in the source. Move each to a settings table or feature-flag service keyed by tenant, give every setting a default, and record who changed it and when. Version the settings schema so that a new release can read old tenant settings. Jobs that ran on a global schedule must run per tenant, using the tenant's time zone and calendar.
What do you do with customer-specific customisations?
Triage every customisation into one of five outcomes: make it configuration, expose an extension point, model it as metadata-driven custom fields, keep that customer on a dedicated deployment, or retire it. Forks of the code base are the one thing a shared platform cannot carry.
| Customisation type | Typical handling | Watch out for |
|---|
| Different label, rule value or threshold | Tenant setting | Settings that interact with each other need validation. |
| Extra fields on a record | Custom fields stored as metadata per tenant | Reporting, search and API output must understand them. |
| Different approval or workflow steps | Configurable workflow definitions | Only worth building if several customers want variants. |
| Customer-specific integration | Per-tenant connector using a stable integration interface, or a webhook | Credentials and failure handling per tenant. |
| Custom report or document layout | Template per tenant | Template changes must not touch other tenants. |
| Custom code in the core | Extension point if it generalises; otherwise dedicated tier | A fork is a signal the product needs a new capability or a different commercial arrangement. |
Count how many customers want each variation. As a rule of thumb, a capability only one customer wants is a services engagement, and one that many customers want is a product feature. Customers who were promised a dedicated install may legitimately stay on one, so most ISVs end with a hybrid: a shared platform for the majority and a small number of dedicated deployments running the same release.
How should you roll out the migration, and how do you roll back?
Roll out in waves. Ship the multi-tenant code to existing installs first, with one tenant each. Then onboard new customers on the shared platform, then migrate existing customers one at a time, each with a reconciliation sign-off. Keep the old install read-only until an agreed date, so a rollback is possible.
Rollback needs honesty about writes. Until the cut-over, the old install is authoritative and rollback is trivial. After cut-over the new platform accumulates changes the old install does not have. Before each customer moves, decide the point of no return: for example "rollback by redirecting back is possible for the first agreed number of days, and only if we replay or accept the loss of new entries". Write that down, with the person who decides.
Four practices make the rollout safe:
- Expand and contract schema changes. Add new structures first, run old and new side by side, remove old structures later, so a release can be reverted.
- Reconcile with evidence. Compare record counts per table, control totals for money and quantity fields, and a sample of records by hand, and have the customer's business owner sign the result.
- Rehearse. Run each customer's migration at least once against a copy and time it. The rehearsal finds the schema surprise before the cut-over does.
- Per-tenant restore. In a shared database, restoring one customer from a backup is not automatic. Build and test a tenant export and restore procedure before the first customer moves.
What are the phases, and what does each one need to finish?
A phased plan keeps the platform change and the customer migration apart. Six phases run from inventory to decommissioning, and each has an exit test that must pass before the next begins, plus a defined way back if it fails.
| Phase | Work | Exit test | Way back |
|---|
| 0. Inventory and decisions | Audit installs, schemas, customisations, contracts, hosting and isolation promises; choose ID strategy and tenancy model | Every install classified: shared, dedicated or retire | Nothing deployed |
| 1. Tenant-aware code | Add tenant key and enforcement, run it on existing installs with one tenant | Existing customers see no change; cross-tenant tests pass | Redeploy previous release |
| 2. Platform foundation | Shared identity, tenant settings, provisioning, metering, tenant export and restore | A test tenant can be created, used, exported and restored | Platform not yet used by customers |
| 3. Pilot customer | Migrate one friendly customer with rehearsal and reconciliation; notify the customer and update contract terms where hosting or sub-processors change (confirm with your legal adviser) | Customer sign-off after an agreed period | Old install still read-only and intact |
| 4. Waves | Migrate remaining shared-tier customers in small groups, with the same customer notice and contract step | Each customer reconciled and signed off | Per-customer point of no return |
| 5. Decommission | Retire old installs after the agreed retention period | Archive confirmed, hosting stopped | None, so confirm archives first |
Worked example (illustrative numbers)
An ISV has 40 customers, each on their own database. The audit finds that 28 have the canonical schema, 8 have small differences (an extra column or a renamed field) and 4 have custom code. After triage, 33 customers go to the shared tier (the 28, plus 5 whose extra columns become custom fields), 3 stay on dedicated deployments of the same release, and 4 move only after their custom code is turned into an extension point or retired. Migration runs as a pilot of 1, then waves of 4, 8 and the remainder, each wave starting only when the last has passed its reconciliation period. The numbers are illustrative; the shape is the point.
When is this the wrong approach?
Moving to multi-tenant is the wrong move when you have a few large customers who need contractual isolation, when each customer's configuration is mostly custom code, or when your deployment per customer is already automated and cheap to run. A single-tenant product with a repeatable deployment pipeline can be a sound business.
It is also premature when the product itself is unsettled. Consolidating onto a platform locks in a data model, so settle the product's core model first. And if the real problem is operating cost, measure what each install costs to host and support before assuming tenancy is the lever.
Glossary: ISV, independent software vendor. Tenant, one customer organisation and its users and data. Dedicated tier, a customer-specific deployment of the same release. Expand and contract, a schema change style that adds before it removes.
How Timeline Digital approaches this
Timeline Digital has built custom software from Islamabad, Pakistan since 2013 and works with SaaS teams remotely. For a migration like this we start by understanding your installs and customers, set the schedule from your requirements in the Plan step (there is no fixed timeframe), and can build a free pilot of 2 to 3 key modules, such as the tenant model and one migration path, for you to test before the final agreement. Source code transfers to you on full payment. Talk to us through the SaaS development company page.