Skip to content
Back to writing

Planning for the Unknown, Within Reason

A feature needs to solve today's business problem, but the decisions made while building it affect tomorrow's options. Hard-coding an assumption can make delivery faster now and a likely change expensive later. Building every possible extension can consume the time available to deliver anything useful.

I try to plan for the unknown within reason. That qualification matters. I cannot know every future request, but I can consider what is already reusable, where the current design makes assumptions, and which changes would be unnecessarily difficult.

Thinking in Lego pieces helps me picture how existing capabilities might support another request. It also raises a practical question: how much work should we do today to keep those pieces useful when the business changes?

Separate an unanswered question from a future possibility

Some unknowns concern the feature being built now. Others concern something the business might need later. They deserve different responses.

For an illustrative inventory and location feature, whether the source quantity includes reservations is a current correctness question. If the feature promises available stock, the team needs an answer before relying on that quantity.

Whether the business will add a second inventory provider next year is a future possibility. It may justify containing provider details, but it does not automatically justify implementing provider routing, configuration screens, or migration tooling today.

Treating both as “future-proofing” obscures the decision. One calls for investigation to establish present behavior. The other calls for judgment about the cost of preserving an option.

Start with evidence of change

A useful reason to preserve flexibility should be explainable in business terms. A planned second fulfillment location, recurring changes to location eligibility, or a provider contract under review offers more evidence than the observation that anything could change someday.

Evidence does not need to provide a complete future specification. It should identify a credible direction of change and the part of the current implementation that would become expensive to untangle.

Suppose a first release serves one location. If another location is already planned, allowing the workflow to receive a location identifier may be a proportionate choice. Assuming one global location throughout order handling would create avoidable coupling.

That still does not establish a need for a general allocation engine. Selecting a location and splitting fulfillment across many locations are different business capabilities. Preserve the smaller option without pretending the larger capability has been delivered.

Compare the cost now with the cost of changing later

The decision is easier to review when the alternatives are concrete:

ChoiceCost todayWhen it earns that cost
Keep the rule in ordinary codeMinimal additional structureThe rule is local, its shape is still emerging, and changing it is inexpensive.
Give the decision a clear boundaryA contract, explicit dependencies, and focused verificationThe decision repeats, provider details would spread, or a plausible change would affect many callers.
Build a configurable capabilityValidation, ownership, user controls, and ongoing operational supportKnown variations recur often enough that controlled adjustment creates business value.

I would default to ordinary code with clear responsibilities, then add a boundary where there is a concrete cost to contain. Configuration should follow evidence that the choices are understood and repeated.

A boundary can be small. A function that decides whether a location is eligible may be sufficient. It does not require a policy framework, a plugin system, or a separate service.

Preserve options without promising interchangeability

Inventory providers may disagree about quantities, locations, freshness, and reservations. Hiding their request formats does not remove those differences. A future integration still has to establish whether its behavior supports the business promise.

That is why adapter boundaries that make change cheaper need to preserve material semantics. Keep provider details contained, while making limitations visible where business decisions depend on them.

The same reasoning applies to storage and deployment. A module can isolate a responsibility inside one application. Extracting it into a service later may still require data ownership decisions, communication changes, and operational work. A clear module boundary preserves a useful starting point; it does not make extraction free.

Allowing for change should produce an honest description of what becomes easier and what remains difficult.

Put uncertainty into the delivery conversation

Planning for the unknown also affects feature estimates. Existing capabilities can reduce implementation work, while uncertainty about their fit can widen the range.

Name the assumption and the consequence. If inventory freshness is sufficient, the current lookup may serve the feature. If it is insufficient, a different refresh strategy or a narrower customer promise may be necessary.

When that difference materially affects delivery, investigate it early. Give the investigation a specific question and a bounded effort. Its result should either resolve the question or identify what still prevents a defensible estimate. Avoid letting “research” become an indefinite substitute for a decision.

An estimate can then explain the agreed scope, the dependencies, and what would cause revision. There is no universal allowance that makes an unresolved business promise safe to commit to.

Record the assumption and the signal to revisit it

Deferring a capability is easier to defend when the current limit is explicit. For the illustrative location feature, a decision record could state that each request selects one location and that splitting an order across locations remains outside the current behavior.

It can also identify the trigger for reconsideration: a confirmed requirement for split fulfillment. The future engineer then has a reason to revisit the decision instead of treating the existing limitation as an accidental defect.

This record should stay short enough to maintain. Capture the current need, the option preserved, the additional machinery deferred, and the evidence that would change the decision.

That is the practical meaning of “within reason” for me. Make today's capability understandable, spend additional effort where a plausible change warrants it, and leave the next engineer enough context to choose differently when the evidence changes.

Discuss on Twitter