In this guide 6 sections
Software written for one business carries that business inside it: its tax format, branch list, approval levels, settings table and reports over a single pool of records. Search for those five. Score each by effort, then fix whatever touches data separation before anything cosmetic, since a leak between customers does more harm than a wrong logo.
Single company assumptions rarely look like assumptions
No code says “one company” out loud. It shows up as a constant, a dropdown or a query without a filter, because the developer who built it had one customer and no reason to ask.
Start with a plain search for company names in templates, for fixed tax rates, and for tables with a single row that everyone reads. Open ten screens as a stranger.
The answers fall into five groups. Each has its own cost. Document formats, branch lists, approvals, settings and reports are the five, and a quick tally of hits per group tells you where the effort will pile up.
- Document and tax formats: invoice numbering, tax labels, rounding rules, letterhead
- Branch and location lists typed into dropdowns or enums
- Approval levels fixed to named people or job titles
- Global settings tables with one row for the whole system
- Reports and exports that read every record without a filter
Where the data is shared by accident
This group is dangerous. A report that sums all invoices will happily add two customers together, and a search box that returns any customer record will expose one business to another.
Check every table for a column naming the owning business, and where it is missing, add it and treat each unfiltered query as a defect. Nightly jobs and CSV imports are the usual misses, because nobody watches them run and nobody tests them with two businesses at once.
File storage needs the same look. Uploaded PDFs sitting in one folder with guessable names are a leak waiting for a curious user, and per-business folders with expiring links close the gap.
Settings, formats and approvals that were never meant to vary
A settings table with one row is easy to fix: give each business its own row and move the invoice prefix, year start and tax labels into it. The trouble is code that reads a constant instead, and every such line needs finding with a search for the literal value.
Approval chains are harder. If the code sends large purchases to the finance head, it means one person, so replace that with roles and a rule each business can edit. Keep the escalation path as data too, so a business with two approvers and a business with five can each work without anyone editing code.
Templates for quotes, invoices and delivery notes tend to hide the company logo and address in the markup, so pull them into per-business fields early. Do it before the second login exists.
- Invoice prefix and number series per business
- Tax names and rates by region, not typed into the template
- Roles with limits, not named individuals
- Logo, address and bank details held as data
Rank the findings by effort and by risk
Score effort and risk. Unfiltered queries score low on effort and high on risk, so they go first, while a new colour scheme scores the opposite and can wait.
Be honest about the expensive ones. Reports with hand-written SQL and no tests take longer to repair than to rebuild, so mark them clearly or the plan will promise a date it cannot keep.
Pilot with a friendly second customer on a copy of the system, because their first week will find assumptions that your search missed. Ask them to import their own customers, print their own invoice and run the month end report, then compare what they see against what the first company sees.
Decide what to change and what to leave
Not every finding needs a fix. If a second customer will never use a feature, hide it, remove the screen from their menu, and move on to the next row of the register. A hidden screen still needs a server-side check, because a menu entry removed from view can still be reached by typing its address.
Write the list into a one-page review for the roadmap owner and ask for fix, hide or defer on each line before promising any buyer a date. Decide before the promise.
Single company assumptions register
Each finding gets its own row. Columns hold the screen or table, the assumption found, its group among the five, effort in days, risk if missed and the decision to fix, hide or defer. A footer lists every table still lacking a business identifier column, with the person assigned to add each one and a date for the first pilot login.
Open a blank worksheet to printQuestions owners ask
How do I know if my software is single company?
Check whether any table, setting or report shows a stranger’s data to a second login, and look for company names or tax rates typed into code or templates.
Is it cheaper to rebuild than to adapt?
Sometimes. If most of the risk sits in unfiltered queries across hundreds of screens, a rebuild of the core can beat patching, and the register shows which case applies.
Can I keep serving my current customer while this happens?
Yes. Work on a copy, add the business identifier column with the existing company as the default, and release in small steps, so the first customer sees no change.
Which assumption should I fix first?
Anything that lets one business read another’s records comes first, meaning queries without a filter, shared file folders and exports, well ahead of formats, labels or approval rules.
