The first customer is wonderfully dangerous.
They tell you what they need. You build it. The software works. They use it. Features accumulate, edge cases get discovered and dealt with, and six months later what began as a prototype looks remarkably like a product.
And because there's only one customer, almost every design decision appears to have been correct.
Then the second customer arrives, wanting essentially the same thing. Except they don't.
Customer One defines the universe
Suppose you're building a system that receives orders from another platform.
Customer One sends an order with a unique order number. Orders are always in one currency. A completed order can't subsequently change. One account belongs to one organisation. Authentication is done with an API key.
None of this looks like a customer-specific requirement — it simply looks like how orders work. So the software grows naturally around it: the order number becomes the primary identifier, currency lives in configuration rather than on the transaction, completed records become immutable, account and organisation get treated almost interchangeably, and authentication ends up implemented somewhere convenient near the API boundary.
There may be nothing wrong with any of this — for Customer One, it could be an excellent system. The difficulty is that you have very little evidence about which parts are the product and which parts are Customer One. You have a sample size of one.
Then Customer Two turns up
Customer Two also sends orders. Their order numbers are unique only within a store. They operate in four currencies. Orders can be amended for 24 hours. Several organisations share an account. Authentication uses short-lived tokens.
Suddenly, decisions that had looked like architecture reveal themselves as assumptions.
This is one of the useful things a second customer does — they don't merely provide more revenue, they provide the first meaningful test of your model of the world.
Some of it survives beautifully: an order is still an order, the workflow may still make sense, most of the reporting might remain valid, and the core processing may need almost no change. Other parts crack immediately, and knowing which is which turns out to matter.
The wrong response is to make Customer Two fit
There's an obvious temptation at this point. Customer One works, the system is stable, and Customer Two is the unusual one — so perhaps Customer Two's integration just gets a few special rules.
If customer == two, construct the identifier differently. If multi-currency is enabled, look somewhere else for currency. If this particular authentication mode is configured, take another path.
This can be perfectly reasonable — not every difference deserves an abstraction. The trouble starts when exceptions are being used to protect assumptions that were never really universal in the first place.
There's a difference between:
Customer Two has an unusual requirement.
and:
Customer Two has demonstrated that our original definition of the product was too narrow.
Recognising which has happened is part of the engineering.
Customer Three is even more interesting
By Customer Two, teams often respond by generalising — sometimes too enthusiastically.
One customer authenticates with an API key. Another uses tokens. Therefore we need an enterprise-grade Universal Authentication Provider Framework capable of supporting any authentication mechanism mankind may devise between now and the heat death of the universe.
Or perhaps you need two authentication implementations.
Customer Three is useful because they start to tell you whether the abstraction built after Customer Two represents a real pattern or just the average of two accidents.
This is where products often begin acquiring their proper boundaries — shaped less by how carefully somebody drew them at the start than by reality pushing against the system from several directions. What remains stable under that pressure probably belongs near the centre. What keeps changing probably belongs nearer the edge.
This happens beyond code
The same effect shows up everywhere.
Your first customer may need a particular deployment model, so deployment and product get entangled. They may use certain terminology that quietly enters the database and then the UI. They may need a report every Monday morning, and before long the system has a concept called a Weekly Report when what actually exists is a much more general reporting capability. They may have three user roles, so you build Administrator, Manager, and User.
Customer Two has five. Now you find out whether those three names represented a genuine permissions model or just three people at Customer One.
Some of the hardest product assumptions to remove are difficult precisely because nobody remembers them being assumptions. They've been there since the beginning.
Don't design for Customer Ten on day one
There's an opposite mistake. If the second customer exposes assumptions, surely the clever move is to anticipate Customers Two through Ten before Customer One even arrives.
Usually not. You don't know what they'll want, and designing a fully general platform in advance often means spending months solving hypothetical variation while the only actual customer is waiting for software.
The first implementation is allowed to be specific. Some specificity is even useful — it gets real software into real use, where the assumptions can finally encounter evidence. The important thing is knowing that this is what you've done.
A decision made for Customer One is not automatically a mistake. Forgetting that it was a decision made for Customer One can become one.
The product emerges from the differences
There's a point, after enough customers, where something interesting happens.
New customers still bring peculiarities — they always will. But increasingly, those peculiarities get handled at boundaries that already exist. Another authentication method doesn't alter the core. Another integration doesn't require the transaction model to change. Another reporting requirement doesn't mean teaching six unrelated services about a new customer.
The centre of the system has become comparatively boring, and that's a good sign. It means the architecture is beginning to reflect the things that are genuinely common rather than the things that happened to be true first.
You could try to predict that architecture before the first customer. Occasionally, you'd even get it right. But Customer Two has a considerable advantage over you.
Customer Two knows what Customer Two wants.