Products rarely become complicated because somebody planned a terrible system. They become complicated one reasonable exception at a time.
Every “yes” changes the product, the code, the test matrix and the future cost of the next yes.
The feature request is rarely just one feature
A customer asks for a custom approval step. Another wants a different notification rule. Sales needs a one-off export. Each request is sensible on its own.
Together they can turn one clean workflow into a configurable machine nobody fully understands.
Exceptions create new states
Adding a setting does not add one line of code. It creates combinations: enabled/disabled, role interactions, old data, migration behaviour, reporting, admin UI, QA coverage and support questions.
The hidden cost of every new option is the state space it creates: the number of different situations the product now has to handle correctly.

Ask whether the request is a pattern
Before customising the core product, ask whether other customers have the same underlying need. Sometimes the right solution is a general capability. Sometimes it is a one-off integration. Sometimes the answer is no.
Do not generalise one customer's organisational chart into your product architecture unless you want to maintain it for everyone.

Price complexity into roadmap decisions
A feature can be commercially valuable and still expensive. Make the ongoing cost visible: additional test combinations, support, documentation, data migration and future constraints.
That lets the company say yes deliberately rather than discovering the price after the contract is signed.
Use extension points intentionally
If variation is part of the business model, design clear extension points — planned places where behaviour is allowed to differ: workflow rules, webhooks, templates, adapters or policy settings.
A deliberate extension model is different from scattered if customerId === ... branches. One is a product capability. The other is a cry for help.
Delete features too
Product management is not only deciding what enters the product. Mature products also need retirement: unused settings, old flows, duplicate reports and compatibility paths that no longer earn their cost.
Every feature has maintenance rent. Some tenants should be evicted.
Protect the shape of the product
Saying no is not stubbornness. It is preserving a product users and engineers can still understand.
The best teams ask not only 'Can we build this?' but 'What does the product become if we do?'
