No history yet

Strategy and Requirements

From Ambiguity to Concrete Plan

A vague problem like "build a photo-sharing app" is not a starting point; it's a puzzle. The first task in any large-scale system design is to transform that ambiguity into a concrete technical plan. This isn't about choosing databases or frameworks yet. It's about defining the problem so precisely that the architectural choices become logical consequences, not guesses.

Clarify requirements: functional goals, scale (RPS, users), latency, and constraints (budget, data retention).

We start by separating requirements into two categories: what the system does and what the system is. This is the classic split between functional and non-functional requirements. Functional requirements are the features users interact with, while non-functional requirements define the system's qualities, like speed and reliability.

Requirement TypeDescriptionExample (Photo-Sharing App)
FunctionalWhat the system must do. The features.Users can upload photos. Users can view photos in a feed. Users can comment on photos.
Non-functionalHow the system must be. The qualities.Photos must upload in under 2 seconds. The feed must be available 99.99% of the time. The system must support 1 million daily active users.

Notice how non-functional requirements are specific and measurable. Vague goals like "the system should be fast" are useless. We need hard numbers that define success.

Defining Success with Metrics

To turn goals into engineering targets, we use Service Level Objectives (SLOs) and Service Level Agreements (SLAs). An SLO is an internal target for system performance (e.g., "99.9% of feed loads will be faster than 500ms"). An SLA is a formal commitment to a customer, often with financial penalties if missed. SLOs should always be stricter than SLAs to provide a buffer.

Two of the most critical metrics are availability and latency.

Availability

noun

The percentage of time a system is operational and able to serve requests. It's often expressed in 'nines.'

Latency measures how long a request takes. Because not all requests are equal, we don't use averages. Averages hide outliers that frustrate users. Instead, we use percentiles, most commonly the 99th percentile, or P99.

P99 Latency=500msP99 \text{ Latency} = 500ms

Capacity and Constraints

With metrics defined, we can estimate the scale the system needs to handle. This is where back-of-the-envelope calculations come in. You don't need exact numbers, but you need to be in the right ballpark. Let's say our photo app has 100 million users, and 1% of them upload a photo each day. The average photo is 2MB.

Daily Uploads=100M users×1%=1M photos/dayStorage=1M photos/day×2MB/photo=2 TB/day\begin{aligned} \text{Daily Uploads} &= 100M \text{ users} \times 1\% = 1M \text{ photos/day} \\ \text{Storage} &= 1M \text{ photos/day} \times 2MB/\text{photo} \\ &= 2 \text{ TB/day} \end{aligned}

What about requests per second (RPS)? If uploads are spread unevenly over the day, say with a 10x peak, we can estimate peak traffic.

Avg. RPS=1M photos24 hrs×3600 s/hr12 RPSPeak RPS=12 RPS×10=120 RPS\begin{aligned} \text{Avg. RPS} &= \frac{1M \text{ photos}}{24 \text{ hrs} \times 3600 \text{ s/hr}} \approx 12 \text{ RPS} \\ \text{Peak RPS} &= 12 \text{ RPS} \times 10 = 120 \text{ RPS} \end{aligned}

These numbers guide our high-level system decomposition. We can immediately see a need for a service that handles photo uploads and another responsible for managing petabytes of storage. This initial breakdown helps us draw boundaries around different parts of the system.

Defining Failure

A critical, often-overlooked step is to define failure domains from the start. A failure domain is a part of your system that can fail independently. If your entire application runs on one server, your failure domain is the whole app. If you use multiple data centers, one data center might be a failure domain.

The goal is to design the system so that the failure of one component has the smallest possible impact on everything else. This is about limiting the blast radius.

Blast Radius

noun

The measure of how much of a system is affected when a component fails. A small blast radius means a failure is contained and has limited impact.

For our photo app, we might identify these failure domains:

  • Upload Service: If this fails, users can't upload new photos, but they can still view existing ones.
  • Feed Generation Service: If this fails, users see a stale or empty feed, but can still view photos directly.
  • A single storage server: If one server holding photos fails, only a fraction of images should become unavailable due to replication.
  • An entire data center: If a whole region goes offline, traffic should be rerouted to another region with minimal user impact.

Thinking about what can break and how it will impact users is not pessimism, it's a core part of designing resilient systems. This initial framing of requirements, metrics, and failure modes provides the blueprint for all subsequent architectural decisions.

Now, let's test your understanding of these core concepts.

Quiz Questions 1/6

Which of the following is a clear example of a non-functional requirement for a photo-sharing app?

Quiz Questions 2/6

An SLO (Service Level Objective) should ideally be less strict than its corresponding SLA (Service Level Agreement).

With a solid set of requirements, you have a firm foundation to justify the trade-offs and choices you'll make when designing the system's architecture.