← All writing2026.10.01 · Software design

Before Designing the System, Peel the Requirement Back to the Real Problem

Stakeholders often describe the end state while engineers hear a specification for today. This is how I learned to separate vision, present needs, extensibility and cost.

The conclusion first

After working on several architecture plans, the most important lesson I learned was not to choose a database earlier or draw more services. It was this: do not translate a sentence about the future into a system before understanding the present problem.

When stakeholders describe a requirement, they often combine today’s need, a future possibility and an ideal end state in one sentence. They may not know which capabilities are expensive or which assumption changes the entire data model. Engineers, meanwhile, may hear “we would eventually like this” as “the first release must support this completely.” Neither side is necessarily wrong. They are speaking at different levels of abstraction and on different timelines.

Without alignment, a team can easily create abstractions, services and deployment units for a scale that has not arrived. The code becomes harder to change, delivery slows down, and infrastructure and operational costs rise before the actual problem has even been validated.

I now peel a large requirement like an onion:

  1. What business outcome is this idea meant to change?
  2. Who encounters which obstacle in the current workflow?
  3. Which capability is necessary for the system to work today?
  4. Which ideas are plausible future directions without a trigger yet?
  5. Can we solve the present problem while leaving a small, testable seam for extension?

The value of systems analysis is not turning every stakeholder sentence into a feature. It is helping everyone agree on the problem worth paying to solve now.

A product vision is not a release requirement

A stakeholder might say:

The system should eventually support different regions, customers and pricing models, and it cannot go down as traffic grows.

This matters as product direction, but it is not yet an estimable requirement. It contains several different questions:

  • Does “multiple regions” mean languages, currencies, regulation or data residency?
  • Are there a few contracted customers, or can anyone create a tenant through self-service?
  • Are there several price lists, or does the product require a composable rules engine?
  • Does “cannot go down” mean reliability during business hours or automatic cross-region failover?
  • Is growth supported by signed customers and measurements, or is it only a possibility?

If engineering implements the broadest interpretation, the result may quickly become a multi-tenant, event-driven, multi-region platform with a rules engine and a general authorization system. The real first release, however, might involve internal staff creating accounts for a small set of business customers and changing prices only occasionally.

The problem is not that those technologies are bad. It is that their timing is unsupported by evidence.

flowchart LR
  V[End-state vision] --> O[Business outcome]
  O --> U[Current users and workflow]
  U --> P[Present obstacle]
  P --> N[Minimum capability now]
  N --> S[Extension seams]
  S --> T[Evidence triggers next stage]

Separate time horizons before discussing architecture

I divide a plan into near-, medium- and long-term horizons, but I do not treat all three as equal commitments.

Horizon Question Architectural response
Now What must exist for us to deliver and operate? Implement, test and observe it
Next Which needs have credible signals that they may arrive soon? Preserve an interface, data boundary or replacement point
Later Which ideas still lack a known date, scale or form? Record assumptions and triggers; do not build yet

The essential distinction is that planning for the future does not mean implementing the future today.

Good architecture does not ignore what may come. It identifies where flexibility is inexpensive. If a product currently uses one payment provider, it does not need a universal orchestration platform on day one. It can still isolate the provider’s statuses behind an adapter so that the core order model does not depend on one vendor’s fields. That is an inexpensive seam, not a prepaid future platform.

First principles: does this constraint exist yet?

This experience changed how I understand first-principles thinking. It does not need to be philosophical. It means temporarily setting aside “systems like this usually use…” and returning to observable facts:

  • How many users and requests exist now, and how do peaks occur?
  • Which data must be immediately correct, and which views may be eventually consistent?
  • What is the business cost of one failure? Can a human recover it?
  • Which requirements come from regulation, contracts or real operational limits?
  • Which constraints are only imagined futures?

Architecture can then start from constraints rather than fashionable nouns.

For example, “traffic may become very high” is not a capacity requirement. A statement that can enter design should look more like this:

Present: peak load and the current bottleneck are measured.
Target: maintain the agreed latency and error rate through the expected growth range.
Trigger: begin the next decomposition only when sustained utilization or queue time crosses a threshold.
Exception: revisit tenancy if a contracted customer introduces different data-isolation requirements.

The numbers do not have to be perfect on the first day. The team does need to distinguish measurements, forecasts and untested assumptions.

How I peel the onion

When a requirement sounds large, I no longer begin with “which technology should we use?” I work through five layers instead.

Layer one: the desired outcome

Ask why the business wants this before discussing the feature.

  • Is the goal to reduce manual work?
  • To onboard the next customer faster?
  • To prevent missing or incorrect transactions?
  • To give operators visibility?

The same feature name can hide very different success criteria.

Layer two: the workflow that exists today

Walk through the current process with the people who perform it. Who receives the input, where is a decision made, who approves it, and how is a failure repaired? The real requirements are often found in verbs, handoffs and exceptions.

Layer three: scope and frequency

Establish the users, transactions, data volume and change frequency. This is not an attempt at perfect forecasting. It prevents the team from treating an administrative action performed a few times a year as a core path that needs automated decisions every second.

Layer four: failure and responsibility

What happens if the capability is late, duplicated or unavailable? Can it be retried? Does it involve money, authorization, regulation or irreversible data? This layer determines how much reliability cost is actually justified.

Layer five: future triggers

Replace “we may need this later” with an agreement about when to reconsider it: a new market is confirmed, partner variation crosses a complexity threshold, manual handling begins to limit operations, or monitoring shows that the current deployment is reaching a capacity limit.

At the center of the onion, a huge requirement usually becomes three things: a capability to implement now, a seam to preserve now, and an idea without enough evidence to enter the current budget.

Extensibility does not mean splitting everything in advance

“Consider future scale” is often interpreted as a reason to introduce microservices, a general rules engine or multi-region infrastructure immediately. Sometimes these are necessary. Each also creates new costs: network failures, consistency, deployment, observability, permissions and more team interfaces.

I care more about a quieter kind of flexibility:

  • Business rules live behind a clear domain boundary rather than being scattered across controllers and UI code.
  • External systems enter through adapters, keeping vendor formats out of the core model.
  • Schemas can evolve, and important events and migrations are versioned.
  • Modules have clear contracts without becoming separate services before the need is proven.
  • Observability tells us when a real capacity or reliability constraint has arrived.

This preserves future options without charging the product the full cost of a distributed system today.

flowchart TB
  R[Present core requirement] --> D[Clear domain boundary]
  D --> A[External-system adapters]
  D --> C[Stable contracts and evolvable schemas]
  D --> M[Capacity and failure signals]
  M -->|No threshold crossed| K[Keep it simple]
  M -->|Evidence appears| E[Decompose or scale]

An estimate should include its assumptions

When discovery is incomplete, a single delivery estimate makes an evolving idea look like a fixed promise. I now bind an estimate to its assumptions:

Item What to make explicit
User scenario Who acts, where the flow begins and what outcome completes it
Current scope What this release includes and excludes
Capacity baseline Measurements, reasonable range and peak shape
Risks Unknowns that could alter the data model or workflow
Extension seams Interfaces preserved now and capabilities deliberately not built
Revisit condition Business or technical evidence that triggers the next stage

This is not avoiding commitment. It puts cost and decisions on the same shared understanding. Stakeholders can choose which risks are worth paying for now and which costs should wait for a signal.

A requirement template I use

I now rewrite abstract visions in a form like this:

When [a type of user], in [a concrete situation], needs to [complete a task],
the system should provide [the minimum necessary capability]
so that [an observable business outcome] occurs.

Current assumptions: [traffic, roles, regions, data and operating frequency]
Not in this release: [unvalidated future capabilities]
Extension seams: [places designed for replacement or growth]
Revisit when: [observable trigger]

The structure forces a useful separation between the platform in our imagination and the product we need to deliver next.

Systems analysis is sequencing the vision, not shrinking it

I used to worry that removing future capabilities from the first release was too conservative. I eventually learned that the more conservative choice is spending months on an unvalidated architecture and making the product harder to change.

Solving the present problem does not mean ignoring the future. A mature design does three things at once:

  • Delivers the smallest complete capability for today’s core workflow.
  • Leaves clear, inexpensive seams where change is likely.
  • Uses business and system signals to decide when to fund the next stage.

A system is not designed once. It evolves with our understanding of the problem, observed traffic and operational constraints. The architect’s job is not to predict every future. It is to make sure the team still has good options when that future becomes real.

Checklist before committing to the plan

  • Are we describing a business outcome, or have we already jumped to features and technology?
  • Have we walked through the current workflow, roles, exceptions and manual recovery?
  • Do traffic and failure costs come from measurements or imagination?
  • Are near-, medium- and long-term needs separated rather than promised together?
  • Does every expensive architectural choice answer a present constraint?
  • Does each future capability have an observable revisit condition?
  • Are we leaving an extension seam, or building a complete platform nobody uses yet?
  • Does the estimate state assumptions, exclusions and risks?

To me, this is the deepest and most underestimated part of systems analysis. The goal is not to collect the largest possible requirement document. It is to keep asking questions until everyone is discussing the same problem, on the same timeline, and the same cost that is worth paying now.