Background
Sections
IntroductionRequirements & Problem AnalysisConstraints & AssumptionsEstimation TechniquesFunctional vs Non-Functional RequirementsMoSCoW PrioritizationSystem Design FundamentalsArchitecture DiagramClass DiagramComponent DiagramData Flow Diagram (DFD)ER Diagram (Entity-Relationship Diagram)High Level Design (HLD)Low Level Design (LLD)Sequence DiagramState DiagramUse Case DiagramData StorageDocument StoresFile StorageGraph DatabasesIn-Memory DatabasesKey-Value StoresNewSQLNoSQL DatabasesObject StorageSQL Databases (RDBMS)Time-Series DatabasesWide-Column StoresDatabase ConceptsACID PropertiesCAP TheoremConsistency ModelsIndexingNormalization & DenormalizationReplicationSharding & PartitioningTransactions & Isolation LevelsScalabilityAuto-Scaling & ElasticityConsensus & Leader ElectionLoad BalancingReplication & Read ReplicasSharding & PartitioningVertical vs Horizontal ScalingAvailability & ReliabilityBackup & Data DurabilityCircuit BreakerData ConsistencyDisaster RecoveryFault Tolerance & FailoverGraceful DegradationHigh AvailabilityNetworkingCDNDNSFirewalls & VPNHTTP & HTTPSLoad Balancer & Reverse ProxyTCP/IP & UDPWebSocketsCachingCache InvalidationCache Read/Write PatternsCaching LayersEviction PoliciesRedis vs MemcachedMessaging & CommunicationDead-Letter QueueIdempotencyKafka vs RabbitMQ vs SQSMessage QueuesPub/SubCompute & ServicesAPI GatewayContainers & OrchestrationMonolith vs MicroservicesServerlessService DiscoveryService MeshWeb Server & App ServerAPI DesignAPI Versioning & IdempotencyAuthentication & AuthorizationGraphQLgRPCPaginationRate Limiting & ThrottlingRESTSecurityAuthentication & AuthorizationData PrivacyEncryptionInput Validation & InjectionOAuth2 & JWTSecrets ManagementXSS & CSRFStorage & File SystemsBackup & RetentionBlock vs File vs Object StorageData Lakes & WarehousesDistributed File SystemsEphemeral StorageObservability & MonitoringDistributed TracingHealth ChecksLoggingMetricsSLI, SLO, SLADesign PatternsBulkhead PatternCircuit Breaker PatternCreational PatternsRate Limiter PatternRetry PatternStructural & Behavioral Patterns

Constraints & Assumptions

6 min read

In a Nutshell

Every system design prompt leaves things unsaid. "Design Instagram" doesn't tell you whether you need to support 1,000 users or 1 billion, whether posts can contain video, or whether the system needs to work across continents. Constraints are the hard limits you're given (or discover). Assumptions are the educated guesses you make to fill the gaps. Stating them out loud is not hedging — it's the act of turning an impossibly broad problem into a bounded one you can actually solve.

2D minimalistic diagram showing a vague cloud labeled 'Design Instagram' on the left, passing through a funnel labeled 'Constraints & Assumptions', producing a clear bounded box on the right with specific parameters like users, data size, and regions

How It Actually Works

What Are Constraints?

Constraints are the hard boundaries of your system — things you can't change or negotiate:

Type Examples
Scale 500M daily active users, 10B API calls/day
Budget Cloud spend capped at $50K/month
Regulatory Data must stay in the EU (GDPR), HIPAA compliance required
Technical Must integrate with an existing Oracle database, mobile-first
Time MVP must launch in 3 months
Team 5 engineers, no ML expertise in-house

Some constraints are stated in the prompt. Others you discover by asking: "Are there any regulatory requirements?" "Is there an existing system we need to integrate with?"

What Are Assumptions?

Assumptions are what you choose to believe when the prompt is silent. The key discipline is to state them explicitly so they can be challenged or confirmed.

Good assumptions sound like:

  • "I'll assume reads outnumber writes 100:1"
  • "I'll assume we don't need multi-region initially"
  • "I'll assume media files are under 10MB"
  • "I'll assume average session length is 5 minutes"

Bad assumptions are the ones you make silently and never validate — they become invisible architectural risks.

Scope and Goals

Once you've gathered constraints and stated assumptions, you draw the scope boundary — what you will and won't build.

This is a single sentence that saves you from designing features nobody asked for:

"I'll consider posting, following, and the news feed in scope. Authentication, payments, analytics, and admin tools are out of scope for this discussion."

Declaring scope is not laziness. It's strategic focus. In a 45-minute interview, you can't design everything well — but you can design one thing very well.

2D minimalistic diagram showing a large circle labeled 'Full System' with a smaller highlighted circle inside labeled 'In Scope' containing core features, and the outer ring labeled 'Out of Scope' with crossed-out features like auth, payments, analytics

The Process

  1. Ask clarifying questions — Who are the users? How many? What's the read/write ratio? Any compliance requirements?
  2. State assumptions explicitly — Write them down. Get agreement from the interviewer (or stakeholder).
  3. Define scope — Name what's in, name what's out. One sentence each.
  4. Revisit as you design — Assumptions can be wrong. If a design choice depends heavily on an assumption, flag it: "This works if reads really are 100× writes. If not, we'd need to rethink the caching layer."

Why This Matters

A system designed for 1,000 users and one designed for 1 billion users are completely different architectures — even if they have the same features. Without stating your assumptions about scale, you can't justify a single architectural decision. Without defining scope, you'll try to design everything and end up designing nothing well.

Seeing It in Action

Scenario: You're asked to design a ride-sharing service like Uber.

Step 1 — Ask clarifying questions:

  • How many drivers and riders? → "I'll assume 1M active drivers, 10M active riders"
  • Which geographies? → "I'll assume a single city initially, with a path to multi-city"
  • Real-time matching? → "Yes, riders should be matched to a driver within 10 seconds"

Step 2 — State assumptions:

  • Drivers send location updates every 3 seconds
  • Average ride lasts 15 minutes
  • Peak traffic is 5× average (rush hour, rain, events)
  • Payment processing is handled by a third-party gateway

Step 3 — Define scope:

  • In scope: Rider requests a ride, system matches to nearest driver, real-time tracking, fare calculation
  • Out of scope: Driver onboarding, payment gateway internals, customer support, surge pricing algorithm details

Step 4 — Derive numbers from assumptions:

  • 1M drivers × 1 update/3s = ~333K location updates/second
  • This immediately tells you: a single database won't handle this write volume. You need an in-memory geospatial index.

Notice how each assumption directly influenced an architecture decision. That's the point.

Interview Questions

  1. Q: Why is it important to state assumptions out loud during a system design interview? Hint: It shows structured thinking, turns ambiguity into a bounded problem, protects against over/under-engineering, and gives the interviewer a chance to steer you. Silent assumptions become invisible risks.

  2. Q: You're designing a file-sharing service. What assumptions would you make about file sizes, and how would they affect your architecture? Hint: If files are < 10MB (documents), a simple upload to object storage works. If files are > 1GB (videos), you need chunked uploads, resumable uploads, multipart processing, and potentially a CDN for delivery. The assumption about size changes every layer.

  3. Q: What's the difference between a constraint and an assumption? Give an example of each for a chat application. Hint: Constraint: "Messages must be encrypted end-to-end" (non-negotiable, externally imposed). Assumption: "I'll assume 90% of conversations are 1-on-1, 10% are group chats" (your best guess to drive design — can be validated later).

  4. Q: How do you decide what to include in scope vs exclude in a 45-minute design interview? Hint: Focus on the core user journey (the 2–3 features that make the system interesting). Exclude anything that's a solved problem you can hand-wave (auth → "use OAuth"), cross-cutting but standard (monitoring, logging), or a separate system entirely (billing, analytics).

  5. Q: Your initial assumption was that the system is read-heavy (100:1 read/write ratio). Midway through the design, the interviewer reveals it's actually write-heavy. What changes? Hint: Caching becomes less effective. You shift focus to write-optimized storage (LSM-tree based stores like Cassandra), write-behind patterns, event sourcing, and async processing. The data model and partitioning strategy may need to change entirely. This tests adaptability.

References

Dive Deeper