1. Project Planning & Scoping
Before writing a single @RestController, write down what this service
actually does, for whom, and what "working" concretely means. Pick a real,
well-scoped backend problem — not a toy CRUD demo, but not an unbounded platform
either:
- A booking system — appointments or reservations against limited capacity, where double-booking is a real bug to prevent, not a hypothetical.
- An inventory/order service — stock levels that must stay consistent under concurrent orders, with a clear order lifecycle and a genuine multi-step saga (Week 18) if it spans more than one service.
- A small SaaS billing or reporting platform — plans, usage, and invoices for multiple tenants (Week 19), where correctness and isolation matter more than feature count.
Whichever domain you pick, define the core domain model and API surface before writing code: what are the two or three central entities, what are the main read and write operations against them, and which of those operations are the ones a reviewer would actually exercise to judge whether the service works. Sketch the key endpoints as a short list — resource, verb, and what changes — the same discipline Week 16's API design lesson used before any of it exists.
Finally, write success criteria down now, not after the fact: a specific, short list of flows that must work end to end (create a booking, prevent a conflicting one, cancel it, see it reflected in availability) decided before you build, so "done" isn't retroactively defined by whatever happened to get built.
package com.codeverse.capstone.booking;
// Written down before any of it exists -- the resource, the verb, what
// changes. Fill this in for your own domain before opening an IDE.
// POST /api/v1/bookings create a booking (or 409 on conflict)
// GET /api/v1/bookings/{id} fetch one booking
// DELETE /api/v1/bookings/{id} cancel a booking
// GET /api/v1/availability?date=... read-heavy -- a caching candidate (Week 11)
public record CreateBookingRequest(Long resourceId, Instant start, Instant end) {}
public record BookingView(Long id, Long resourceId, Instant start, Instant end, String status) {}
2. Architecture Decisions & Which Advanced Modules Fit
With the service scoped, make deliberate choices — and be ready to justify each one in writing, not just make it. This capstone spans a much wider toolkit than the original 15-week version, which makes restraint the actual skill being tested:
- Monolith vs. services (Weeks 9–10, 17–18) — a single well-structured Spring Boot application is the right default for a capstone-sized domain. Only split into a second service if there's a genuinely separate responsibility, and only reach for Config Server/Eureka/Gateway (Week 17) if you're actually running more than one or two services — not because the course covered it.
- Sync, async, or a saga (Weeks 9–10, 18) — a synchronous call for anything the caller needs an immediate answer to; an event for anything that can happen after the response has gone out; a full saga with compensating actions and a transactional outbox only if a real multi-step, multi-service transaction genuinely exists in your domain.
- REST, GraphQL, or both (Weeks 3, 16, 21) — REST remains the right default for a capstone-sized API; add GraphQL specifically if your domain has a genuinely nested, client-driven shape (a dashboard needing different fields per view) that would otherwise need several bespoke REST endpoints.
- What needs caching, batching, or background processing (Weeks 11, 20) — cache read-heavy, slow-changing data; reach for Spring Batch only if there's a real bulk/offline workload (a nightly import, a large export), not for anything that fits comfortably in a normal request.
- Auth model (Weeks 6–7, 19) — Week 6's JWT-based auth is enough for most capstones; running your own Authorization Server or building multi-tenant isolation is only worth the complexity if your domain genuinely has third-party clients or multiple tenants sharing infrastructure.
The justification is the actual work here. "I kept this as one service, with plain JWT auth and no saga, because the domain is small and every one of those techniques would add failure surface for no real benefit" is an architectural decision; using every technique from the course by default is not. Write the reasoning down alongside each choice — Week 26's write-up depends on it.
A capstone that picks Advanced Spring Data (Week 15), a saga with an outbox (Week 18), and a progressive canary rollout (Week 24) — each with a clear, specific reason tied to the domain — demonstrates stronger engineering judgment than one that bolts on GraphQL, Spring Batch, and a full Authorization Server because the syllabus covered them. Depth and justification beat breadth every time a reviewer actually reads the write-up.
3. Implementation, in a Sensible Order
Build in an order that lets you validate each layer before the next depends on it — the same incremental discipline this course used from Week 5 onward, now spanning the whole service and whichever advanced modules Section 2 selected:
// 1. Entities and persistence first (Weeks 4-5, 15) -- get the domain
// model into a real database with migrations and any Specifications
// or projections you need, before any HTTP layer exists.
// 2. REST (and GraphQL, if chosen) layer (Weeks 3, 16, 21) -- controllers,
// DTOs, validation, versioning and pagination conventions over that
// persisted model; confirm every core flow works unauthenticated.
// 3. Security (Weeks 6-7, 19) -- add authentication and authorization
// once the unsecured flows are already correct, not before.
// 4. Service-to-service, messaging, or a saga (Weeks 9-10, 17-18) --
// ONLY if Section 2's architecture actually calls for it.
// 5. Caching or batch processing (Weeks 11, 20) -- applied last, to
// endpoints or workloads Section 2 identified as needing it, once
// their unoptimized behavior is already correct.
This order matters for the same reason it mattered in every earlier week's exercises: it's far cheaper to discover your entity relationships or API shape need to change while only the persistence and REST layers exist, than after security, sagas, and caching are all built on top of an assumption that turns out to be wrong. Validate each layer — a passing request against it, by hand or by test — before adding the next.
4. End-of-Week Checkpoint
Before moving into Week 26, confirm all of the following are true and working:
- ✅ The scope, API surface, and success criteria from Section 1 are written down, not implicit in whatever got built.
- ✅ Every architectural choice from Section 2 — including which advanced modules were deliberately excluded — has a one- or two-sentence written justification.
- ✅ The persistence and REST layers work correctly, unauthenticated, exercised by hand or a quick test, before security was added.
- ✅ Authentication and authorization are in place and correctly restrict access to the operations that need it.
- ✅ Any chosen advanced modules (a saga, GraphQL, caching, batch) are implemented and individually validated, not just present in the code.
With all five true, the implementation is solid enough to build Week 26's testing, observability, and deployment pass on top of — and to write the final capstone defense against.