Where should customer complexity live?
What history shows about scaling a standardized product as enterprise customers demand more complexity.
Enterprise customers create exceptions. The question is not whether those exceptions exist, because they always do. It is where the work created by them ends up. Complexity does not disappear when a company holds its architecture. It gets assigned somewhere, sometimes without anyone deciding.
Follow the work
A requirement that does not fit the product has to be absorbed by someone. There are five places it can go, and each produces a different company.
The platform already has a model for the requirement. The customer sets values inside a schema the vendor owns.
The vendor builds and maintains the abstraction; customers reuse it.
Mostly in product and platform R&D, with relatively low incremental cost per customer.
The schema stops fitting, and requirements start arriving that have no place to go.
Customers or partners add behavior inside a runtime and a contract the vendor defines and versions.
The customer or an app developer, inside the vendor’s boundary.
In platform engineering, and in the vendor’s testing surface.
The contract has no version or no deprecation path, so the extension becomes permanent.
Custom code, workflows, and integrations accumulate in the customer’s own instance or estate.
The customer’s IT organization.
Nowhere in the vendor’s accounts. In the customer’s cost of change.
Customer-specific code can accumulate outside the vendor’s visibility while the vendor’s own release metrics remain healthy.
Systems integrators configure, integrate, and migrate, often billing the customer directly.
The partner’s consultants.
On the partner’s income statement and the customer’s budget.
The vendor loses sight of how its product is actually deployed, and inherits partner quality.
The vendor’s own people configure, integrate, migrate, and support each enterprise customer.
The vendor’s services organization.
Immediately, in services gross margin.
Growth becomes headcount-bound, and delivery capacity gates new logos.
Software margins do not tell you what complexity costs
Two companies, two structures, and in both cases the software economics and the deployment economics sit far apart inside the same business.
The software and the work required to deploy it can have completely different economics inside one company, in one year, across one customer base.
When the vendor carries implementation itself, the cost surfaces in its own accounts. Zuora disclosed a quarter in which services cost more to deliver than they generated.
You cannot read the cost of customer complexity from software margins alone.
The same underlying difficulty can produce a high services line, a low one, or none at all, depending on how delivery was structured. If implementation moves to systems integrators, the vendor’s statements can improve even when substantial deployment work still remains outside the vendor. Everything in the accounts stays accurate. The picture is still incomplete. You have to follow the work.
Four things the record actually supports
Each rests on a company’s own filings, changelogs, or documentation rather than on commentary about them.
Build the abstraction before the variations arrive
Adyen supports more than 100 payment methods on one platform, and those methods behave differently from each other in flow, failure, and settlement. Its own documentation shows a payment method being requested and configured per store, with bulk actions for adding several at once.
The hundredth payment method entered a model that already existed. A genuinely novel requirement would require the model itself to change.
Know what you can take back
Salesforce retires old API versions on a published schedule, and retired calls fail outright. Its own retirement notice states that the retirement does not include Apex classes, Apex triggers, Visualforce pages, or versioned metadata components in managed packages.
Old tenant-resident code is not swept up by that mechanism. Salesforce holds a hard boundary at the integration layer and declines to enforce one inside the customer’s instance.
Build the replacement before removing the old surface
Checkout extensibility became available on all Shopify Plus stores on 30 January 2023. Fourteen days later Shopify announced that checkout.liquid was deprecated and would stop working for in-checkout pages on 13 August 2024.
Merchants had a supported destination in market before the deprecation was announced, then roughly eighteen months before the first enforcement date.
Decide who carries the implementation labor
nCino’s filings describe systems integrators performing most implementation for enterprise and larger regional institutions, billing those customers directly, while nCino delivers services itself at the small end. Guidewire cut a full-year revenue outlook in March 2024 because partners were leading cloud engagements faster than expected. Zuora kept the work in-house.
Implementation complexity can be moved. It cannot be declared gone.
Where should the complexity go?
None of these is superior to the others. They carry different costs, and the cost of choosing by accident is higher than the cost of choosing any one of them deliberately.
Put it in the product when
- The requirement repeats across customers
- It fits a general abstraction you can name
- You can own and version it
- Each new instance should get cheaper
Put it in an extension layer when
- Customer variation is legitimate and specific
- You cannot predict every use case
- Behavior can sit inside a stable contract
- You know how that contract will evolve
Put it with partners when
- Implementation labor is substantial
- Deployment needs domain expertise you lack
- You want to preserve software economics
- The work can be done without fragmenting the product
Keep it in vendor services when
- The implementation knowledge is strategically valuable
- The product is still learning from deployments
- The work cannot yet be standardized
- You are knowingly accepting the margin trade
Services intensity is not automatically failure. Guidewire has run the last two of these together, taking capped-fee implementations to accelerate cloud migration while shifting engagements to partners. Adyen absorbed enormous variation on one platform for two decades. Workday combined a single codeline with a customer extension platform for years. The pattern is deliberate placement rather than elimination.
The dangerous state is accidental complexity
The dangerous state is not customization itself. It is customer-specific work accumulating somewhere without anyone deliberately deciding that is where it should live.
Each of these is survivable alone. What makes them costly together is that none of them arrives as a decision. They surface later, as a deployment timeline nobody can explain.
How to route a new requirement
Four questions, then one test that matters more than the route you took to reach it.
Does a general model already exist?
Yes → configuration. Add the instance and move on.
Will the requirement repeat?
Yes → expand the product abstraction now, while there is one instance to design against.
Can it live inside a controlled extension boundary?
Yes → extension layer, on a versioned contract you can later change.
If not, who should carry the work?
Vendor services · Partner · Customer
Then the test: is that destination intentional, measured, and priced accordingly?
Five questions for your own company
Answerable this week by people who already know. Mark each honestly.
When the last three large customers asked for something unusual, did engineers add an instance to a model that already existed, or invent a new one?
Which customer-specific behaviors could you actually remove, and on what notice?
If you eliminated your most problematic customization surface, what would customers move to?
Who performs the majority of implementation work for your largest customers, and on whose invoice does it appear?
Are implementation economics improving as you scale, or moving off your financial statements?
Answer the five above. This is not a maturity score. It measures how much of your customer complexity currently has a destination somebody can name.
A company can maintain one codebase, one release cadence, and one version of its product long after customer complexity has moved somewhere the architecture diagram does not show.
It may be sitting in customer code, in an implementation partner’s delivery practice, in a services organization, or in a product abstraction that absorbed it successfully years ago and never made a sound.
So ask where the last customer’s complexity went. And whether that is where you intended it to go.