Title: Lecture 3 — Designing Your System as Layers, Not Guesses
Course: AIINFRA 303: Capstone Project > Section: Week 03 — System Architecture and Full-Stack Infrastructure Design

📖 Lecture — Designing Your System as Layers, Not Guesses

Every production AI system, however small, is a stack of layers cooperating to turn raw data into a decision someone can act on. Across AIINFRA 100–302 you built pieces of this stack in isolation: you containerized a service, deployed to cloud, wired up CI/CD, served a model, fine-tuned one, wrapped it in an agent with MCP tools, retrieved context with RAG, and reasoned about security and cost. This week's job is to stop treating those as separate skills and start treating them as layers of one system — and to draw that system on paper (well, in Markdown) before you write another line of application code. The five layers, in order of data flow

Layer | Responsibility | Typical capstone examples | State that lives here
Data ingestion / storage | Get raw data in and durably store it | Object storage bucket, Postgres, uploaded documents | Source-of-truth data, raw files
Feature / preprocessing | Clean, chunk, embed, transform | Embedding pipeline, ETL job, RAG chunker | Derived artifacts (embeddings, features) — usually rebuildable
Model serving | Run inference against a trained or fine-tuned model | vLLM/TGI endpoint, fine-tuned adapter, hosted API call | Model weights, KV cache (ephemeral)
API / application layer | Expose business logic to users or other systems | FastAPI/Flask backend, agent orchestrator, MCP server | Session state, request logs
Observability | See what the other four layers are actually doing | Logs, metrics, traces, dashboards | Time-series metrics, trace spans

Notice the last column: naming where state lives is not optional. A huge share of production incidents trace back to someone assuming a layer was stateless when it wasn't (an in-memory cache that silently became the system of record) or stateful when it wasn't (a "durable" queue that was actually an ephemeral container volume). When you diagram your system this week, every box needs an answer to "if this component restarts, what do I lose?" The MLOps principle underneath all of this: pipelines as code The single design principle that separates a capstone that survives contact with Week 8's design review from one that doesn't is this: your ML workflow should be defined in code, not in your head or in a notebook you ran once. That means your data pipeline, training/fine-tuning steps, and deployment steps are expressed as version-controlled scripts, configs, and infrastructure definitions — the same discipline you already apply to application code via CI/CD in AIINFRA 101. This buys you three things directly relevant to your capstone:

- Reproducibility — anyone (including future-you, six weeks from now) can regenerate your model or your feature set from the same inputs and get the same outputs.
- Testability — a pipeline expressed as code can be unit-tested and run in CI, the same way you'd test an API endpoint.
- Dev/prod parity — the Docker Compose stack you sketch this week and the production deployment you build toward in later weeks should differ only in scale and secrets, not in structure.

Diagrams as code: C4 with Mermaid To document architecture in a way that survives your capstone's actual lifespan (a semester, not a slide deck), we use the C4 model — Context, Containers, Components, Code — but for this week you only need the top two levels. A Context diagram shows your system as a single box and the people/external systems around it. A Container diagram opens that box up into the deployable units (API, database, cache, model server) and shows how they talk to each other. Mermaid ships native C4 syntax (C4Context, C4Container), which means your diagram is a .md file that renders directly on GitHub with no plugin and no install — and it lives in your repo next to the code it describes, so it version-controls alongside every other change. If your system later grows past what Mermaid's still-experimental C4 support handles cleanly, C4-PlantUML or Structurizr DSL give you a stricter, CI-renderable alternative with a single versioned workspace model — but for a capstone-scale system, Mermaid is almost always enough. Correcting two habits that quietly wreck capstone architectures Misconception 1: "A real system uses microservices." In practice, fewer than 5% of applications genuinely benefit from a microservices split at their starting size. Splitting your capstone into six services before you have six people's worth of operational load just multiplies your deployment surface, your network failure modes, and your debugging time — for no offsetting benefit. A well-structured modular monolith — one deployable API service with clearly separated internal modules — is the correct first architecture for almost every capstone in this course. You can always extract a service later, once you have evidence (an SLO you can't meet, a team boundary you actually have) that demands it. Misconception 2: "I should design for the scale I might eventually have." Over-optimizing for bottlenecks and organizational boundaries that don't exist yet trades away the simplicity and speed you need right now in exchange for ceremony you don't need yet. Your Week 2 requirements and SLOs describe the load and team you actually have (usually: one developer, a handful of test users, modest request volume). Design for that. This week's diagram should look boring and justified, not impressive and speculative — and Discussion 3 will ask you to defend exactly that restraint. The diagram you produce in Lab 3 is not a one-off homework artifact. It is the reference architecture you will present, defend, and likely revise at the Week 8 design review, so it is worth getting the layer boundaries and state ownership right now.