Build the MVP: understand the problem
- Source
- From the Staff AI System Design course
- By
- Sourav Banerjee
- Last updated
- 8 Nov 2026
Alice, a procurement analyst in Tenant A, wants to draft a supplier email from text she provides and reopen the saved answer. Build that request path before adding document search, background jobs, or a platform of separate services.
This is an educational design for a hypothetical customer. All workload, latency, quota, retention, and token figures below are illustrative assumptions. The executable lab verifies a local slice with fixture identity and a deterministic model. It does not deploy an enterprise service or call a hosted model.
Follow five learning phases: understand the problem, learn and design, observe and experiment, think like a Staff engineer, then validate and carry forward. The detailed material stays within the original MVP scope.
Before this lesson, read the T18.1 overview for the complete customer journey and target architecture. Then return here to build the first saved-draft path.
1. Before This Stage
No system exists. There is no previous stage to inherit, no benchmark, and no existing identity integration. Alice currently copies text into an unmanaged drafting tool and saves the result manually. That workflow is the hypothetical starting requirement, not observed customer research.
Before diagram. Text alternative: Alice has a requirement; the platform has no implemented components.
The smallest useful outcome has four properties. A trusted identity identifies Alice. A server submits approved text to a model. The server saves the completed answer before reporting success. A later read returns only Alice’s own saved request.
2. The Customer Contract
Ask what Alice will do with the answer. She reviews and sends the email herself. The application neither sends messages nor makes procurement decisions. There are no internal document connectors, so it must not claim to answer questions from company policy or cite unavailable sources.
Before the formal contract, picture five moments in Alice’s workflow:
| Supplier-email moment | Name for the idea | Guarantee and limit |
|---|---|---|
| Alice proves which account she uses; Bob still cannot open her saved draft | Authentication identifies the caller; authorisation checks access | Trusted code checks tenant and user on every history read; model text cannot grant access |
| Alice is willing to wait about five seconds for a saved draft | Service-level objective (SLO) | A measured target for a defined request population; a fast example does not prove it |
| Saving the answer and its completed label must agree | Database transaction | Local changes commit together or roll back; the separate provider is not inside that transaction |
| Alice double-clicks Submit after a network pause | Idempotency | Reusing the same scoped key can return the existing result; it does not guarantee one provider execution after every possible crash |
| Alice sees “saved” and expects to reopen the answer | Acknowledgement boundary | Report completion after the answer commit; partial or unsaved text is not a completed saved draft |
The 95th percentile, or p95, is the latency threshold met by 95% of the measured requests. Counting timeouts and errors alongside latency prevents fast rejections from looking like success. The rest of the lesson makes these promises precise. Learn the consequence first, then use the formal term to explain your design.
| Requirement | Illustrative acceptance criterion | Design consequence |
|---|---|---|
| Draft from supplied text | One authenticated POST returns an answer and request ID | Synchronous API with a model adapter |
| Reopen a draft | A committed completed answer can be read by its owner | Durable relational request history |
| Isolate history | Tenant B cannot list or fetch Tenant A requests | Trusted tenant/user predicates on every read |
| Stay responsive | Healthy pilot p95 below five seconds | Deadline hierarchy and measured latency breakdown |
| Bound spending | Expected 1,200 input and at most 300 output tokens | Provider token limits and usage counters in the real integration |
| Protect supplied text | Only approved non-sensitive pilot text; credentials stay on server | Explicit provider boundary, no prompt/token logging |
| Retain briefly | Proposed 30-day history policy | Deletion/backup policy must be implemented before a real pilot |
The five-second value is a proposed service-level objective (SLO), a target measured over a defined population. It is not a promise this lesson has demonstrated. Define the pilot SLI, or service-level indicator, as elapsed time for valid authorised draft requests from server receipt to final response, with timeouts counted as failures. Track rejection rate separately so rejecting requests cannot make latency look healthy. Include user-side latency to detect network delays outside the server measurement.
The scope is one active pilot user, 200 requests during an eight-hour workday, and a brief 0.5 requests per second peak. Tenant B is a negative-test fixture, not a second launched customer. Confirm real demand, provider text handling, deployment region, and identity requirements before a pilot.
3. What This Module Covers
| Topic | Depth | What you should be able to do |
|---|---|---|
| Requirements and architecture methodology | Build depth | Turn user outcomes into boundaries, alternatives, and failure tests |
| Estimation and capacity planning | Build depth | Compute demand and identify which limit the units describe |
| Networking fundamentals | Design depth | Locate DNS, connection, TLS, and HTTP failures on the path |
| APIs and streaming protocols | Build depth | Build/debug a request contract and defend JSON versus streaming |
| Database architecture | Design depth | Explain keys, indexes, transactions, and the external-call gap |
| End-to-end AI application design | Build depth | Implement the representative auth-to-model-to-history slice |
No modules are revisited here.
Nearby concepts have narrower treatment:
| Module | Treatment here | Where it is taught |
|---|---|---|
| Design documentation and communication | Context only: use an ADR, without teaching a documentation portfolio | T18.13, build depth |
| Gateway and service communication | Context only: name an ingress role; do not teach service-to-service architecture | T18.7, build depth |
| Identity and access control | Context only: trusted caller scope and fixture checks | T18.7, build depth |
| Background execution systems | Deferred: no durable jobs or worker recovery | T18.3, build depth |
| Document ingestion and indexing | Deferred: supplied text only, no internal knowledge pipeline | T18.4, build depth |
Build depth means explaining, choosing, building a representative slice, observing failure, and mitigating it. Design depth requires architectural explanation and a small design exercise. There are no revisit modules in T18.2.
Before starting, be able to read basic Python, JSON, SQL, and HTTP. Stop at the MVP boundary. Defer retrieval, durable workers, caches, Kubernetes, GPU hosting, and advanced tenant scheduling until a requirement motivates them.
4. First Walk Through the Failure
Suppose the server calls the model and immediately sends Alice the text, then tries to save it. The database write fails. Alice saw a success, but reopening the request yields nothing. A model response alone has failed the customer contract.
Reverse the acknowledgement boundary. First insert a processing row and commit it. Then call the provider without an open database write transaction. After generation, update the row to completed with its answer and commit. Only then return a successful answer. If the final write fails, return a storage error; the earlier row may remain processing and need investigation.
This ordering creates a visible ambiguity: the provider might have generated and charged for an answer that the database never recorded. A database transaction cannot atomically include an independent hosted-model API. Preserve the request ID, avoid automatic retries, and make this gap explicit. T18.3 can later strengthen job recovery; this lesson does not claim exactly-once model execution.
Key Takeaways
- The smallest useful outcome has four properties. A trusted identity identifies Alice, a server submits approved text to a model, the answer is saved before success is reported, and a later read returns only her own request.
- Commit a
processingrow, call the provider with no database write transaction open, then commitcompletedwith the answer. Only then return success, and return a storage error if the final write fails. - A database transaction cannot include an independent hosted model. A failed final write can leave an answer the provider generated and charged for but the database never recorded, so keep the request ID and do not retry automatically.
- The five-second p95 is a proposed SLO for valid authorised requests from server receipt to final response, with timeouts counted as failures. Track rejection rate separately so fast rejections cannot make latency look healthy.