Scenario-System Design (SSD)
Design for tomorrow, build for today.
- Author Shurn
- Version 1.0.0
- Licence CC BY-SA 4.0
- Canonical ssd.shurn.me
The Problem: The Waste Pendulum#
Most engineering teams oscillate between two destructive extremes. Both feel productive in the moment; both burn the same finite resource — engineering time. This oscillation is the Waste Pendulum.
The Trap of Under-Engineering
Writing code only for the immediate ticket, without considering adjacent flows. The first delivery is fast — until the next request arrives. Then come the constant rewrites, the schema mutations, and the architectural debt that compounds with every subsequent change.
The Trap of Over-Engineering
Speculative Generality
Writing complex abstractions, unneeded generic layers, and runtime hooks for theoretical futures that never happen. The architecture is impressive; the delivery is slow; the flexibility ships as dead code.
Core value proposition: SSD decouples the cognitive scope of architecture from the execution scope of code delivery.
The Core Axiom#
“Architect the system across the full scenario horizon (Tomorrow), but implement code only for the validated requirement (Today).”
Tomorrow is Mental
Exhaustively explore the problem space, domain boundaries, and data schemas before committing code.
Today is Minimal
Deliver only the leanest functional code to fulfil immediate value. Because the architectural keel was laid with the horizon in mind, future extensions require zero overhauls.
The Three Phases of SSD#
SSD operationalises the axiom as a repeatable, three-phase workflow.
-
Phase 1: Scenario Horizon
- Brainstorm all probable scenarios, variations, edge cases, and adjacent capabilities — e.g., secondary payment providers, asynchronous queue processing, multi-tenancy.
- Timebox rule: constrain this exercise to 1–2 hours to avoid analysis paralysis.
-
Phase 2: Keel Architecture
- Architectural Seams: Design stable data schemas, boundary contracts, and modular interfaces capable of supporting all identified scenarios.
- Non-Breaking Foundations: Ensure primary entities and relationships can scale additively without requiring structural migrations later.
-
Phase 3: Minimal Core Build
- Minimal Functional Footprint: Implement only the synchronous logic and endpoints required for the validated immediate request.
- Deliberate Omissions: Explicitly identify, document, and defer non-essential features, speculative abstractions, and secondary workflows from today's active pull request.
- Rapid Extension Trigger: Define the production metric or business signal that validates initial success and unlocks the deferred scenarios.
A Concrete Walkthrough#
Consider a deceptively simple ticket: “Send a confirmation email when an order completes checkout.” Three engineers pick up the same ticket — and land in three very different places.
-
Path A: The Under-Engineered Trap
Rewrite inevitablejava// CheckoutService.java — built for one ticket public class CheckoutService { public void completeOrder(Order order) { orderRepository.save(order); // Hardcoded to a single provider, single channel sendgridClient.sendEmail(order.getEmail(), "Order confirmed"); } }
The failure: when the business inevitably requests SMS order updates next month,
CheckoutServicemust be refactored — breaking existing unit tests and risking checkout stability. -
Path B: The Over-Engineered Trap
Speculative generalityjava// Built for a future that never arrives NotificationChannel channel = channelFactory .forTransport(Transport.SMS) // no SMS users yet .withPluginLoader(dynamicClasspath) // speculative plugin system .publishTo(kafkaEventBus) // no throughput to justify it .build(); // Plus four empty tables: sms_messages, slack_messages, // discord_messages, webhook_endpoints
The failure: immense development delay, high maintenance overhead, and dead code solving problems that never materialise.
-
Path C: The SSD Approach
Strictly additive- Phase 1 (Horizon): acknowledged email, SMS, and webhook alerts as potential adjacent flows.
- Phase 2 (Keel Architecture): defined a lean
NotificationGatewayinterface with asend(recipient, message)contract, and added anotification_channelenum column to the schema. - Phase 3 (Minimal Core Build): implemented only
EmailNotificationGateway. - Deliberately Omitted: SMS third-party SDKs, background worker queues, and retry mechanisms.
java// Phase 2 — the keel: one stable seam public interface NotificationGateway { void send(Recipient recipient, Message message); } // Phase 3 — today: the only implementation that ships public class EmailNotificationGateway implements NotificationGateway { public void send(Recipient recipient, Message message) { sendgridClient.sendEmail(recipient.email(), message.body()); } }
Rapid extension: when SMS is requested later, it is delivered as a strictly additive class implementing
NotificationGateway— with zero modifications toCheckoutService.java// Next month: strictly additive. CheckoutService is untouched. public class SmsNotificationGateway implements NotificationGateway { public void send(Recipient recipient, Message message) { twilioClient.sendSms(recipient.phone(), message.body()); } }
Operational Guardrails#
Three rules keep SSD from sliding back into either trap of the Waste Pendulum.
-
The Timebox Rule
Brainstorming is bounded. Avoid design committees and infinite horizons.
-
Logic Over Abstraction
Prefer clear, readable logic over premature design patterns.
-
The Extension Proof
Verify that future scenarios can be built purely additively before merging.
Frequently Asked Questions & Anti-Goals#
Does Phase 1 violate YAGNI (You Aren't Gonna Need It)?
No. YAGNI governs the execution footprint — never write speculative runtime code, and SSD strictly honours YAGNI in Phase 3. However, SSD prevents architectural blindness: while you should not code for tomorrow, you must understand the problem space so your data models and interface seams don't trap you into a rewrite.
What if our Phase 1 predictions are wrong?
That is precisely why Phase 1 is strictly timeboxed and Phase 3 is kept minimal. Because you wrote no unused business logic or speculative abstractions, if requirements pivot completely, zero engineering hours were wasted maintaining dead code.
When should you NOT use SSD?
SSD is unnecessary for throwaway proof-of-concept scripts, 48-hour hackathon prototypes, simple internal CRUD tools with no business logic, or static scripts. It is designed for production services with anticipated lifecycles beyond a single sprint.
Practical Artefact: SSD Pull Request Template#
Drop this template into your repository's .github/PULL_REQUEST_TEMPLATE.md
to make SSD a routine part of every change you ship.
### Scenario-System Design (SSD) Summary #### 1. Scenario Horizon (Tomorrow) * Immediate Request: [Brief summary of the primary ticket] * Considered Scenarios: * [Scenario A: e.g., Support for secondary payment provider] * [Scenario B: e.g., Webhook-based asynchronous completion] #### 2. Keel Architecture (Tomorrow) * Structural Hooks: [e.g., Decoupled payment processing interface from checkout domain] * Schemas & Interfaces: [e.g., Stable entity contracts and boundary definitions supporting all considered scenarios] #### 3. Minimal Core Build (Today) * Immediate Scope: [Single synchronous endpoint handling primary provider] * Deliberately Deferred: [e.g., No secondary API clients or background queue workers implemented yet] * Rapid Extension Signal: [Building Scenario A/B triggers when monthly transaction volume exceeds threshold]
Embed the Badge#
Signal that your repository follows the Scenario-System Design process. The snippet below
renders a compliance badge in your project's README.md:
[](https://ssd.shurn.me)
Attribution & Citation#
When referencing SSD in documentation, talks, or publications, use the following citation:
Shurn. (2026). Scenario-System Design: Design for Tomorrow, Build for Today. Available at: https://ssd.shurn.me