Capstone — Building a Small gRPC Service
🏁 Capstone: Building a Small gRPC Service
The System: UserService + OrderService
Requirements: an end user (with a bearer token) calls OrderService.CreateOrder; OrderService needs to look up the caller's details from UserService — a genuine internal service-to-service call, secured with mTLS; a client can then subscribe to live order status updates via streaming; every call on both services is logged.
Step 1: Schema Design (Chapter 2)
Step 2: The Service-to-Service Call (Chapters 1, 3, 7)
Creating an order needs the customer's name — OrderService fetches it by calling UserService directly, exactly the internal service-to-service pattern Chapter 1 named as gRPC's original purpose, secured with the mutual TLS Chapter 7 covered.
Step 3: Streaming Order Status (Chapter 4)
A server-streaming RPC lets a client subscribe to live updates as an order moves through processing.
Step 4: Interceptors Tying It Together (Chapter 6)
A shared logging interceptor applies to both services; an auth interceptor on OrderService validates the end user's bearer token before createOrder ever runs.
Step 5: Putting It All Together
- A client (holding a bearer token) calls
OrderService.CreateOrder. - OrderService's logging interceptor records the attempt; its auth interceptor validates the token, rejecting with
UNAUTHENTICATEDif invalid. - The
createOrderhandler callsUserService.GetUserinternally, over an mTLS-secured channel — UserService's own interceptors verify the client certificate before responding. - The order is created and returned to the original client.
- The client calls
WatchOrderStatusto receive live status updates as the order is processed.
| Course Concept | Where It's Used in This App |
|---|---|
| Service definitions & messages (Ch.2) | user.proto / order.proto |
| Service-to-service calls (Ch.1, 3) | OrderService calling UserService's GetUser |
| Server streaming (Ch.4) | WatchOrderStatus |
| Interceptors (Ch.6) | Shared logging + auth on OrderService, mTLS check on UserService |
| Bearer tokens & mTLS (Ch.7) | End-user auth on OrderService; service identity on the OrderService→UserService call |
💻 Coding Challenges
Challenge 1: Add Error Handling to the Internal Call
Extend Step 2's createOrder handler so that if UserService.GetUser returns NOT_FOUND, the whole CreateOrder call fails with a clear, matching error rather than a generic one.
Goal: Practice propagating a meaningful gRPC status code (Chapter 5) across a service-to-service call.
Challenge 2: Design a Client-Streaming Addition
Design a new client-streaming RPC, ImportOrders, that lets a client submit many orders in one call and receive a single summary response with the total count created.
Goal: Practice applying Chapter 4's client-streaming mode to a new scenario within this capstone's schema.
Challenge 3: Justify the Interceptor Order
Explain why Step 4 registers the logging interceptor before the auth interceptor on OrderService, referencing Chapter 6's material.
Goal: Practice applying the interceptor-ordering lesson to this capstone's specific setup.
Chapter 5 established that deadlines propagate across a call chain — but only if the code actually threads them through. If createOrder's call to UserService.GetUser doesn't derive its own deadline from the incoming client call's remaining time budget, the two calls end up with independent timeouts: the original client's deadline could expire while OrderService is still waiting on a UserService call that has no idea a time budget even exists. Every internal call made from within a handler needs to explicitly forward (or derive from) the deadline it received, not start a fresh, unrelated one — exactly the kind of detail that's easy to get right in a single-service example and easy to silently miss the moment a real call chain like this one exists.
🎉 Course Complete
That's the full gRPC course — from the RPC model and HTTP/2 transport through Protocol Buffers, code generation, all four streaming modes, error handling and metadata, interceptors, authentication and security, microservices/load balancing, and finally a real two-service system combining all of it. Together with API Types & Design and API Testing & Tooling, this completes the site's "APIs & Integration" area.