← Back to Design Thinking

Design Thinking

Decision-Making Under Real Constraints

Senior engineers excel at architectural decisions under uncertainty. Learn time vs correctness vs cost trade-offs, build vs buy vs defer, and MVP vs long-term architecture.

Advanced22 min read

Senior engineers distinguish themselves not by knowing more technologies, but by making better decisions under real constraints: incomplete requirements, wrong assumptions, deadline pressure, and budget limits. This topic explores how to think about architectural decisions when you don't have the luxury of perfect information.


Designing Under Incomplete or Wrong Requirements

The Reality

In practice, you will often design systems where:

  • Requirements are vague: "Build something like X" with no specs
  • Requirements are wrong: Stakeholders don't know what they need yet
  • Requirements change: The product pivots before you ship
  • Requirements conflict: Latency vs cost vs reliability can't all be optimized

Senior Approach

  1. Name the uncertainty: "We're uncertain about X. Here's what we're assuming."
  2. Design for change: Choose components that can be swapped or extended
  3. Build reversible decisions first: Prefer choices you can undo
  4. Defer irreversible ones: Don't lock in until you have signal

Example: Vague "Design a Feed"

Junior response: "I'll use Cassandra for write scalability and Redis for caching."

Senior response: "Before choosing storage, I need to clarify: Is this activity feed or algorithmic? What's the read/write ratio? Can we start with a simple append-only design and evolve? I'll assume activity feed for now and design so we can swap to ranking later."


Time vs Correctness vs Cost Trade-offs

The Triangle

Every decision sits in a triangle. You can optimize for two, rarely all three:

PriorityWhat You GainWhat You Sacrifice
Time firstShip fast, learn from usersTechnical debt, may need rewrite
Correctness firstRobust, scalable, maintainableSlower to market, higher cost
Cost firstFits budget, efficientMay limit scale or features

When to Optimize for Time

  • Product-market fit unknown
  • Competitive pressure
  • Learning phase (MVP, experiment)
  • Reversible decision

When to Optimize for Correctness

  • Financial transactions, compliance, safety
  • Core platform that many teams depend on
  • Irreversible decisions (data model, external contracts)

When to Optimize for Cost

  • Known scale, predictable load
  • Cost-sensitive business model
  • Optimization phase after PMF

Real-World Example: Startup vs Enterprise

Startup: Time first. Ship in 6 weeks with a monolith, PostgreSQL, and minimal infra. Accept that you'll refactor. Correctness on money movement only.

Enterprise: Correctness and compliance first. SOC2, multi-region, audit logs from day one. Time and cost are secondary.


Build vs Buy vs Defer Decisions

Framework

  1. Build when: Core differentiator, no good vendor fit, or vendor lock-in risk is high
  2. Buy when: Commodity problem, faster to integrate, vendor has scale/expertise
  3. Defer when: Requirements unclear, not blocking, or can use a simple interim solution

Build vs Buy Matrix

FactorLean BuildLean Buy
AuthSimple JWT, sessionAuth0, Cognito, Firebase Auth
PaymentsDon't buildStripe, Braintree
SearchDB LIKE, then Algolia/ElasticElasticsearch, Algolia
EmailDon't buildSendGrid, SES
Real-timePolling → WebSocketsPusher, Ably, or build

Senior Insight: The Hidden Cost of Build

Building seems cheaper until you count: ongoing maintenance, security patches, scaling, monitoring, and opportunity cost. Buying often wins for non-differentiating capabilities.

Senior Insight: The Hidden Cost of Buy

Vendor lock-in, rate limits, pricing changes, and lack of customization can make buy painful. For core capabilities, build may be worth it.


MVP vs Long-Term Architecture Decisions

The Tension

  • MVP: Fast, simple, good enough to learn
  • Long-term: Scalable, maintainable, fits future vision

Senior Approach: Strangler Fig Pattern

Design the MVP so it can grow:

  • Modular monolith: Clear boundaries even if deployed together
  • Database: Choose schema that can be split (avoid cross-table joins at boundaries)
  • APIs: Internal interfaces from day one, even if same process
  • State: Stateless services, external state store

What to Get Right Early

  • Data model for core entities (hard to change)
  • Authentication/authorization model
  • External contracts (webhooks, APIs you expose)

What You Can Fix Later

  • Caching layer
  • Queue implementation
  • Read replicas vs sharding
  • Service boundaries (can split monolith)

Thinking Aloud Like a Senior Engineer

Problem: "We need to add payments. We have 3 months and 2 engineers."

My first instinct: "Let's build a payment service. We need full control."

But wait — payments are regulated. PCI compliance. Chargebacks. Currency handling. Building is a 12+ month project for a small team.

I'm thinking: "Buy. Stripe or similar. Integrate in 2–4 weeks. Focus our engineers on what differentiates us."

What about lock-in? "Stripe has good abstractions. We can use their API and keep our data model. If we need to switch later, we'd migrate transactions—possible but painful. For now, speed matters more."

What about cost? "At our scale, Stripe's fees are acceptable. When we're processing $10M/month, we can reassess. That's a good problem to have."

Decision: Buy (Stripe). Defer building. Revisit at 10x scale. Document as a reversible decision with a review trigger.


How a Senior Engineer Thinks About Constraints

  1. Name constraints explicitly: Time, budget, team size, compliance
  2. Separate reversible from irreversible: Optimize confidence for irreversible
  3. Quantify when possible: "2 weeks to buy vs 3 months to build"
  4. Plan for evolution: "We'll reassess when we hit X"
  5. Document the trade-off: "We chose Y because of Z. We're accepting A. We'll revisit if B happens."

Best Practices

  1. Never assume perfect requirements: Design for change
  2. Make the triangle explicit: "We're optimizing for time; we accept cost"
  3. Default to buy for commodity: Auth, payments, email, search
  4. Default to build for differentiation: Core logic, unique workflows
  5. Defer when unclear: Simple solution first, evolve with learning

Common Interview Questions

Intermediate

Q: How do you decide between building and buying a component?

A: I consider: (1) Is it core to our product? Build. (2) Is it a commodity with good vendors? Buy. (3) Are requirements unclear? Defer—use simplest option. I also factor in team expertise, timeline, and total cost of ownership (maintenance, not just initial build).

Senior

Q: You're told to ship in 6 weeks but the right architecture would take 3 months. What do you do?

A: I'd identify what's reversible vs irreversible. For reversible choices (caching, queue tech), I'd ship the fastest option. For irreversible (data model, external API contracts), I'd push back or scope down. I'd document technical debt and create a plan to address it. I'd also ask: "What's the cost of being 6 weeks late?" Sometimes the right answer is to extend the timeline.


Summary

Decision-making under constraints is a core senior skill. Key takeaways:

  • Name uncertainty and assumptions before proposing solutions
  • Time vs correctness vs cost: optimize for two, rarely three
  • Build vs buy vs defer: commodity → buy, differentiation → build, unclear → defer
  • MVP vs long-term: modular monolith, clear boundaries, reversible decisions first
  • Document trade-offs: what you chose, why, what you're accepting, when to revisit

FAQs

Q: How do I push back when requirements are wrong?

A: Frame it as risk: "If we build for X and it's actually Y, we'll spend Z weeks redoing it. Can we validate X with a quick prototype first?" Offer a low-cost way to reduce uncertainty.

Q: When should I insist on more time for correctness?

A: For safety, money, compliance, or data model. When the cost of being wrong is very high or the decision is hard to reverse.

Q: How do I explain technical debt to non-technical stakeholders?

A: "We're taking a shortcut now to hit the deadline. It will cost us X extra time later if we don't address it. Here's when we should revisit." Tie it to business impact.

Keep exploring

Design thinking works best when combined with practice. Explore more topics or apply what you've learned in our system design practice platform.