332 lessons taught you individual tools. This Part builds one real system with all of them at once — starting now, with the blueprint.
Every Part up to this point picked one topic and went deep on it in isolation: Clean Architecture (249) got its own lesson, JWT (262) got its own lesson, the Outbox pattern (294) got its own lesson. That's the right way to learn a tool — but it leaves one question quietly unanswered. A real production system doesn't get to use Clean Architecture or JWT or the Outbox pattern one at a time. It needs all of them, at once, making room for each other, inside one codebase, under one deadline.
Starting with this lesson, you're going to design and build that system. It's called OrderFlow — a production-grade order-management API for an e-commerce business — and the next thirteen lessons build it piece by piece, each one reaching back into a discipline this course already taught in depth and showing you exactly how it earns its place in one real, cohesive codebase. This lesson is the blueprint: what OrderFlow actually needs to do, what constraints it has to survive, and which lesson answers which piece of that.
OrderFlow is an order-management API for an online store. A customer browses a product catalog, places an order made up of one or more line items, and from that point on the system takes over: charging the customer, reserving the stock, arranging shipment, and keeping the customer informed — all while staying fast, available, and honest about what's actually happening, even when a downstream step is slow or temporarily broken.
OrderFlow's domain is deliberately familiar — you've seen fragments of it throughout the Advanced tier, including the checkout-timeout incident in lesson 321 and the OrderService examples back in 240 and 242. Now it becomes one real system, with a fixed vocabulary you'll see reused, unchanged, for the rest of this Part and into the next one:
| Core entity | What it represents |
|---|---|
| Customer | A registered account holder who can browse products and place orders |
| Product | An item in the catalog — name, price, and available stock |
| Order | One checkout — belongs to exactly one Customer, moves through a status lifecycle |
| OrderItem | One line within an Order — a Product, a quantity, a price snapshot |
And five named services, each owning one responsibility in the pipeline that turns a placed order into a fulfilled one — you'll see every one of these built out, lesson by lesson, for the rest of this Part:
| Service | Responsibility |
|---|---|
| OrderService | Validates and places an order; the synchronous, customer-facing path |
| PaymentService | Charges the customer through a payment provider |
| InventoryService | Reserves and releases stock against Product availability |
| ShippingService | Schedules a shipment once payment and stock are confirmed |
| NotificationService | Emails the customer at each meaningful step |
You now know, individually, how to layer an application (249), authenticate and authorize a request (260-263), design a schema and query it efficiently (247, 273, 277), cache the right things (265, 266, 280), move slow work off the request thread (165), and let services communicate reliably through events (286-294). What you haven't yet had to do is decide, inside one real set of requirements, which of those tools actually apply, in what order, and how they hand off to each other — the part of engineering judgment that only shows up when the whole system has to work together, not just each piece in its own lesson.
OrderFlow exists to force that integration. It's deliberately not a toy — it carries four real, production-shaped constraints that a system this course already used in passing (the checkout flow from lesson 321, the OrderService from 240/242) never had to fully answer. Naming those constraints up front is the entire point of this lesson: everything that follows is a direct response to one or more of them.
Every one of these constraints rules out a naive design on its own. Scale rules out an in-process cache with no shared backing store, and rules out any state kept only in one instance's memory across requests. Availability rules out calling the payment provider synchronously and making the customer's browser wait on it. Real integrations rule out assuming a downstream call always succeeds on the first try. None of this is new theory — it's the reason lessons 165, 249, 265, 266, 280, and 286-294 exist in the first place. OrderFlow is where you finally see why.
OrderFlow gets built one deliberate layer at a time, in an order chosen so that each lesson can lean on the one before it, exactly the way a real project would be sequenced. This is your Part's map — the second half (340-346) continues the same build under a different author, so the names and structure below carry forward unchanged all the way to the course's final lesson.
Before 334 gives these entities a real home in a layered project, here's the plain shape of OrderFlow's domain — deliberately unstructured for now, just to fix the vocabulary:
public class Customer
{
public Guid Id { get; set; }
public string Email { get; set; } = "";
public string Name { get; set; } = "";
}
public class Product
{
public Guid Id { get; set; }
public string Name { get; set; } = "";
public decimal Price { get; set; }
public int StockQuantity { get; set; }
}
public class Order
{
public Guid Id { get; set; }
public Guid CustomerId { get; set; }
public OrderStatus Status { get; set; }
public List<OrderItem> Items { get; set; } = new();
public DateTime PlacedAtUtc { get; set; }
}
public class OrderItem
{
public Guid Id { get; set; }
public Guid ProductId { get; set; }
public int Quantity { get; set; }
public decimal UnitPriceAtPurchase { get; set; } // a snapshot, not a live lookup — the price at the moment of purchase
}
public enum OrderStatus { Placed, PaymentConfirmed, StockReserved, Shipped, Cancelled }Meaning: Nothing here is architecturally interesting yet — no layers, no interfaces, no async pipeline. That's deliberate. 334 takes this exact vocabulary and gives it a real, enforced structure; nothing about the entities themselves changes from here forward.
Here's the single scenario every remaining lesson in this Part keeps coming back to, described once, plainly, before any of the machinery exists to actually build it:
A customer, already logged in, adds two products to a cart and hits "place order." The request has to be authenticated as that specific customer (335), the order and its line items have to be written to the database correctly and efficiently (336), the product prices shown to them had to come from a cache that was never allowed to go stale (337). Then — critically — the HTTP response has to come back fast, without making the customer's browser sit and wait while a card is actually charged, stock is actually reserved, and a shipment is actually scheduled (338). Those three things then have to happen reliably, in the right order, exactly once each, even if the process handling them crashes and restarts halfway through (339). Every one of those parenthetical lesson numbers is a real requirement this one paragraph creates — not an abstract exercise.
Every previous Part handed you one tool at a time and let you use it on a small, purpose-built example — a hammer here, a level there, each demonstrated on its own. That's the right way to learn what a hammer does. But nobody has ever built a house by demonstrating a hammer once and calling it done. A real house needs the hammer, the level, the wiring, and the plumbing, all working together, in the right order, none of them getting in the other's way — and it needs a blueprint that says which tool does which job, and when. This lesson is that blueprint. The next thirteen lessons are the build.
Each constraint from the Big Picture section maps to specific tools you already have — this table is the precise version of "why this lesson sequence, in this order":
| Constraint | Answered by |
|---|---|
| Scale — more than one instance, no shared in-process state | Clean Architecture's swappable Infrastructure (249/334), IDistributedCache (266/337) |
| Availability — checkout can't block on slow dependencies | Hosted services (165/338), durable messaging (286-294/339) |
| Correctness under concurrent access — many customers, one stock count | Repository pattern and query optimization (247/273/336), idempotent consumers (290/339) |
| Real integrations — payment, inventory, shipping as separate concerns | Abstractions owned by the Application layer (249/334), independent consumer services (288/339) |
| Who's allowed to do what | JWT + policy-based authorization (260-263/335) |
Nothing in this Part introduces a pattern you haven't already learned in depth. Every lesson from here through 339 opens by naming the earlier lesson it's building on, and spends its time on the application, not the fundamentals. If a concept feels unfamiliar while reading ahead, the fix is to revisit the cited lesson number, not to expect this Part to re-teach it from scratch.
OrderService, PaymentService, InventoryService, ShippingService, and NotificationService are named as separate responsibilities because that's good design regardless of how they're deployed — as modules inside one application, or eventually as separate deployable processes. This Part builds them as clearly-separated logical services first; messaging (339) is exactly what would let any of them become a genuinely separate deployment later without the others needing to change. Don't read "five services" as "five containers" yet — that's a deployment decision, not a design one.
Building PaymentService, InventoryService, and ShippingService as if the payment provider always responds instantly and successfully, then trying to bolt retries and idempotency on afterward. The constraints in this lesson — availability, real integrations — are exactly why 338 and 339 treat "a downstream call can be slow or fail" as a first-class design input from the start, not an afterthought.
Assuming every one of OrderFlow's four constraints demands the heaviest possible tool — Kafka for absolutely everything, a distributed cache for absolutely every read, a background service for absolutely every write. Each upcoming lesson makes a deliberate, scoped call about where its tool actually earns its cost inside OrderFlow specifically — not a blanket rule that the fanciest available tool always wins.
You've seen the blueprint OrderFlow is built from. Let's confirm the shape of it is clear before the build actually starts.
1. Which of the following are OrderFlow's four core entities, as fixed in this lesson?
Correct: B
Why B is correct: Customer, Product, Order, and OrderItem are the exact four entities this lesson establishes, and they carry unchanged through the rest of this Part and into the sibling lessons that continue the build.
Why A is incorrect: These are plausible-sounding e-commerce names, but not the ones this lesson actually established for OrderFlow.
Why C is incorrect: Same issue — none of these match the fixed vocabulary this lesson defines.
Why D is incorrect: "Inventory" and "Shipment" are close to real OrderFlow concepts (they're services, not entities), but this isn't the entity list the lesson actually names.
Reinforcement: Getting this exact vocabulary right matters — every remaining lesson in this Part, and the ones that follow it, assume these four names without redefining them.
2. Why does this lesson insist that the next thirteen lessons "apply" existing material rather than teach new patterns?
Correct: B
Why B is correct: This is stated directly in "Why Does It Exist?" — the gap this Part fills isn't missing knowledge of individual tools, it's the judgment to combine them correctly under one system's real, simultaneous constraints.
Why A is incorrect: The course simply chose to spend its final Part on integration and application rather than more isolated topics — it's a deliberate pedagogical choice, not a shortage of material.
Why C is incorrect: The Simple Example section already shows real, if intentionally unstructured, C# code — this Part absolutely includes implementation.
Why D is incorrect: OrderFlow is built with concrete code across every upcoming lesson — it isn't a diagram-only exercise.
Reinforcement: This Part's job is integration and application judgment, not new syntax or new patterns.
3. A reader assumes that because OrderFlow has five separately named services, it must already be a microservices architecture deployed as five separate containers. What does this lesson say about that assumption?
Correct: B
Why B is correct: Common Confusion #2 addresses this directly — clear logical separation is good design regardless of deployment shape, and messaging is what would make a later split into separate deployments possible without forcing that decision now.
Why A is incorrect: This is exactly the premature conclusion the lesson warns against — logical service names don't dictate a deployment topology on their own.
Why C is incorrect: The lesson doesn't rule this out either — it explicitly leaves the deployment question open for later, rather than answering it in either direction here.
Why D is incorrect: The separation is a real design decision (each service owns one responsibility) — it does affect the codebase's structure, just not necessarily its deployment topology yet.
Reinforcement: Logical separation and deployment separation are two different decisions, made at two different times, for two different reasons.
4. According to the Big Picture section, which OrderFlow constraint most directly explains why the checkout HTTP response can't wait on the payment provider to finish charging the customer?
Correct: B
Why B is correct: Availability is defined precisely as "checkout has to stay fast and responsive even when a downstream dependency is slow or down" — that's exactly why the checkout response can't block on a synchronous payment call, and it's the direct motivation for background processing (338).
Why A is incorrect: Observability is about being able to see what's happening after the fact, not about the request/response timing itself.
Why C is incorrect: Real Integrations explains why the payment provider has unpredictable latency and failure modes in the first place, but Availability is the constraint that specifically drives the design choice not to block the response on it — the two work together, they aren't unrelated.
Why D is incorrect: This directly connects to Availability, as stated in the Big Picture section.
Reinforcement: Availability is what pushes slow, external work off the synchronous request path — exactly what lesson 338 builds.
The blueprint is set. Next: 334 gives OrderFlow's entities and services a real, enforced structure — applying lesson 249's Dependency Rule to an actual project layout for the first time.
dotnetmadeeasy.com — Learn C# and .NET, the right way.