The 80/20 of SaaS Customization: Build vs. Let Users Shape
A 2x2 for which customization requests deserve a sprint, which deserve a setting, and which should never have been a ticket.
Every SaaS team has a customization backlog. The question is what to do with it.
The default answer is to build everything customers ask for, prioritized by who asked loudest. That is how you end up with a codebase full of per-customer flags and a sprint that ships nothing new. The opposite default, "we do not customize," is how you lose deals.
Neither extreme is right. The right answer is to sort each request into one of four buckets, and treat each bucket completely differently. That sort is the whole game.
The framework
Two questions per request:
- How specific is this need to one user (or one segment)? Low if everyone wants it. High if it is one customer's workflow.
- What happens if a user gets it wrong? Low if the worst case is a confused user. High if the worst case is corrupted data, broken auth, or a billing dispute.
Plot a request on these two axes and you get four quadrants.
| | Low risk if user gets it wrong | High risk if user gets it wrong | |---|---|---| | High user-specific need | SHAPE. Let users customize themselves. (Layouts, filters, columns, sort orders, saved views.) | BUILD WITH GUARDRAILS. Build the workflow. Expose the safe knobs. (Custom fields, alert rules, role-scoped permissions.) | | Low user-specific need | DEFAULT. One sensible default. Maybe a setting. (Date formats, theme, notification frequency.) | BUILD IT YOURSELF. No customer should touch this. (Auth, billing, data integrity, audit logging.) |
The trap most teams fall into is treating every customization request as if it lives in the bottom-right quadrant. Every request gets a PR. Every PR gets reviewed, QA'd, deployed. The cost is the same whether the request is "let me add a column" or "let me invoice in a new currency." That sameness is the bug.
The four quadrants want four different responses. Let me walk through each.
Top-left: SHAPE
Examples: Column visibility, filter values, sort order, saved views, dashboard layout, table density, default sidebar state, what timezone displays mean.
Why it belongs here: Every user has different preferences. The cost of getting it wrong is "the user sees something they did not want," which is annoying but not catastrophic. The user can fix it by reshaping.
The right response: Do not build a feature. Declare the axis as shapeable. Let the user customize it themselves.
This is the quadrant that eats SaaS engineering teams alive, because every request looks small and reasonable. "Can you add a column" is the canonical example. We wrote a whole post on the real cost of treating that request as a sprint task. The short version: three engineer-days per column, and the queue never empties.
The structural answer is to give users a constrained interface for shaping their own view. The developer declares what is shapeable. The user adjusts within those bounds. No PR, no review, no QA, no deploy. The Crafter wrote the rules once. The Shapers customize forever.
Concretely, in ShapeKit:
const dashboardSkill = ShapeKit.define({
name: 'Account Health Dashboard',
columns: {
account_name: { fixed: true },
health_score: { fixed: true },
mrr: { shapeable: true, default: true },
last_login: { shapeable: true, default: false },
contract_renewal: { shapeable: true, default: false },
csm_owner: { shapeable: true, default: false },
},
maxVisibleColumns: 6,
sortable: ['health_score', 'mrr', 'last_login'],
savedViews: { perUser: true, perRole: 'admin' },
})
The user opens the Shape panel, picks the columns that matter to their workflow, saves the view. Done. You did not write a feature. You wrote a definition.
If 60 percent of your customization tickets fall into this quadrant (and at most B2B SaaS companies they do), this is where the highest leverage lives.
Top-right: BUILD WITH GUARDRAILS
Examples: Custom fields on a record, alert rules and thresholds, role and permission definitions, automation triggers, webhook configurations, branded email templates.
Why it belongs here: Customers genuinely have different needs (their CRM, their org chart, their alerting policy is unique to them). But getting it wrong has real consequences. A misconfigured alert rule can either page the wrong person at 3am or hide a real outage. A broken webhook can drop revenue events. A bad permission rule can leak data across roles.
The right response: Build a real feature for it, and design the user-facing controls so that the dangerous configurations are unreachable by default.
The work here is real. You are building an opinionated configuration surface. You decide which axes are exposed and what the safe ranges are. The customer cannot accidentally lock themselves out, send their data to a typo'd endpoint, or grant admin to "Everyone."
A pattern that works: validate at write time, not at run time. If a customer writes a webhook that points at https://typo.example.com, your config UI should reject it on save with "we could not reach that URL" rather than silently accepting it and dropping events for the next month. Same for permission rules, alert thresholds, automation conditions. The configuration UI is your contract with the customer about what is safe; it should refuse to accept anything that violates the contract.
This quadrant is where most SaaS products earn the right to charge money. The hard, valuable work is building these flexible-but-safe surfaces. Doing it well is what separates a real platform from a pile of conditionals.
Bottom-left: DEFAULT
Examples: Date format, currency display, theme (light/dark), notification cadence, default landing page, language.
Why it belongs here: Most users want one thing. A few users want a different thing. Nobody is going to file a serious bug if the default is wrong, because they can change it in a settings page in 10 seconds.
The right response: Pick a sensible default. Expose a setting. Move on.
The mistake here is over-engineering. You do not need a workflow editor for "what timezone do you want." You need a dropdown.
Some teams treat every preference as a research project. Six weeks of design discussions about whether the date format should be inferred from browser locale, IP, account billing address, or explicit user setting. The answer is "infer from browser, let the user override in settings, ship it." Ten engineer-hours, not ten engineer-weeks.
Default decisions matter less than people think. Reversibility matters more. As long as the user can change the default in one click and the product remembers their choice, you have done your job.
Bottom-right: BUILD IT YOURSELF
Examples: Authentication and session handling, billing and subscription state, multi-tenant data isolation, audit logging, encryption at rest, regulatory compliance flags.
Why it belongs here: Customers do not have meaningfully different needs in this dimension (everyone wants their auth to work and their billing to be correct). But the cost of getting it wrong is catastrophic. A broken auth flow leaks data. A broken billing system loses revenue or generates lawsuits. A broken tenant isolation boundary ends your company.
The right response: No customer-facing knobs. You make the decisions. You enforce the invariants in code. You audit the implementation. You hire someone whose entire job is making sure these systems work.
This is the smallest quadrant by ticket count and the largest by stakes. It deserves senior engineers, dedicated test coverage, and explicit refusal to "just expose a small config option." Every config option in this quadrant is a future incident.
If a customer asks for "custom auth," the answer is almost always "we do not do that, but we support SAML/SSO/OIDC, here is the integration." If a customer asks for "custom billing," the answer is "no, but we support custom contract terms via your CSM." You wall off the dangerous quadrant with named alternatives that live in the top-right (where you have already built the safe surface).
Why this matters more than the framework itself
Frameworks are easy to draw and hard to use. The actual discipline is forcing yourself to sort the next ticket in your queue, right now, before you scope the work.
Run this exercise on the last ten customization tickets your team shipped. Be honest about which quadrant each belonged in. My experience advising teams: 50 to 70 percent of "small" customization tickets are top-left tickets that were treated like top-right tickets. We spent sprints building features for things that should have been declared shapeable.
The math is brutal. If a top-right feature takes a sprint and a top-left "feature" takes three engineer-days, treating top-left work like top-right work is a 5x to 10x tax on your roadmap. That is not a rounding error. That is the difference between shipping the headline feature this quarter and slipping it again.
The fix is not "do less customization." The fix is to stop using the wrong tool for the wrong job.
- Top-left → declare it shapeable, let the user shape it.
- Top-right → build it with guardrails, ship the configuration surface.
- Bottom-left → pick a default, expose a setting.
- Bottom-right → build it yourself, expose nothing.
When a customer request lands in the queue, the first question is not "how do we build this." It is "which quadrant is this." If the answer is top-left, the second question is "why is this a ticket at all."
ShapeKit is built for the top-left. The Crafter declares the shape space, the Shaper customizes within it, your sprint stops bleeding. Free tier is live. See pricing or see how it works to understand the constrained shaping model.
The other three quadrants are still your job. We just want the top-left back.