> ## Documentation Index
> Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Case Study Guide

> Structure, content checklist, and rubric to write your case study

## What Great Case Studies Show

A great case study demonstrates **how you think**, not just what you built. Interviewers have seen thousands of CRUD apps -- what they have not seen is a candidate who can explain why they chose optimistic locking over pessimistic locking for inventory management, and what failure mode they accepted as a trade-off.

Here is what separates good from great:

| Aspect           | Weak                       | Strong                                                                                                                                       |
| ---------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Problem**      | "Built an e-commerce site" | "Solved inventory sync across 3 warehouses with 99.9% accuracy"                                                                              |
| **Architecture** | "Used React and Node"      | "Chose React with Next.js for SSR because marketplace SEO drives 60% of organic traffic; Node for real-time WebSocket support"               |
| **Trade-offs**   | "Used PostgreSQL"          | "PostgreSQL over MongoDB for ACID transactions on payment flows; accepted slower writes and more rigid schema migrations for data integrity" |
| **Impact**       | "It works"                 | "Reduced checkout time by 40%, handled 10K concurrent users at p95 latency under 200ms"                                                      |
| **Failures**     | Not mentioned              | "Webhook delivery failed silently for 3 hours until we added idempotent handlers with a dead letter queue"                                   |

<Tip>
  **Think like a Staff Engineer**: Every decision should answer three questions -- "Why this? What were the alternatives? What would you do differently?" If you cannot answer all three for a given technology choice, you either do not understand the choice deeply enough, or you made it by default rather than by design. Both are worth examining.
</Tip>

***

## Required Sections

Each section below has a specific purpose in the evaluator's mind. Understanding that purpose helps you write content that lands.

<Steps>
  <Step title="Overview" icon="circle-info">
    **Purpose**: Quick snapshot for readers to decide whether to keep reading. This is your elevator pitch -- make every word count.

    * Project name and one-line value proposition (not a feature list -- a problem statement)
    * GitHub link(s) with good READMEs. A repo with no README or a boilerplate README actively hurts your case study.
    * Live demo URL (if applicable). Even a 30-second Loom video walkthrough is better than nothing.
    * Team size and your role. Be specific: "Led backend architecture for a 4-person team" is stronger than "Full-stack developer."
    * Timeline (e.g., "3 months, part-time"). This gives evaluators context for what is a reasonable scope.

    <Tip>
      If your project is not deployed, record a 2-minute demo video and link it. Evaluators spend more time on case studies with visual proof.
    </Tip>
  </Step>

  <Step title="Goals of the Project" icon="bullseye">
    **Purpose**: Show you understand the business context, not just code. This section separates engineers who build features from engineers who solve problems.

    * **Business/User Goals**: What problem does this solve? Who benefits? Frame in terms of user pain, not technology. "Sellers lose 15% of orders because inventory is out of sync across warehouses" is stronger than "We need real-time inventory updates."
    * **Technical Goals**: Performance targets, scalability requirements, reliability targets. Be specific and measurable -- "fast" is not a goal; "p95 latency under 200ms at 10K concurrent users" is.
    * **Non-Goals**: What is explicitly out of scope? This is one of the most underrated sections. Listing non-goals shows you can scope a project, which is the skill that separates mid-level from senior engineers.

    ```markdown theme={null}
    ## Goals
    - Support 10K concurrent users with p95 latency under 200ms
    - Process payments with PCI compliance via Stripe Elements
    - Real-time inventory updates across 3 warehouses with 99.9% accuracy

    ## Non-Goals
    - Mobile app (web-responsive design for MVP; native app planned for v2)
    - International shipping (US-only for v1 to avoid tax complexity)
    - Seller analytics dashboard (deferred to reduce launch scope)
    ```

    <Tip>
      **Pro move**: For each non-goal, briefly explain **why** it is out of scope. "Mobile app (deferred to v2)" is fine. "Mobile app (deferred because our user research showed 85% of sellers manage inventory from desktop)" is excellent -- it shows you scoped based on data, not just convenience.
    </Tip>
  </Step>

  <Step title="System Architecture Overview" icon="diagram-project">
    **Purpose**: Give readers the 10,000-foot view before diving in. This section answers "what does the system look like?" and more importantly "why does it look that way?"

    **Tech Stack Table** (required). Every row needs a "Why" column. "Used React" is not a decision; it is a default. Show what you considered and rejected:

    | Layer    | Technology        | Why This Choice                                                           | What We Considered                                                                         |
    | -------- | ----------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
    | Frontend | Next.js 14        | SSR for SEO (60% of traffic is organic), App Router for better DX         | Remix (less mature ecosystem), plain React SPA (poor SEO)                                  |
    | Backend  | Node.js + Express | Team familiarity, native WebSocket support, shared language with frontend | Django (would require Python expertise we lacked), Go (faster but steeper learning curve)  |
    | Database | PostgreSQL        | ACID guarantees for payment flows, JSONB for flexible product attributes  | MongoDB (no ACID for multi-document transactions at the time), MySQL (weaker JSON support) |
    | Cache    | Redis             | Session storage, rate limiting, pub/sub for real-time events              | Memcached (no persistence, no pub/sub)                                                     |
    | Payments | Stripe            | Best documentation, reliable webhooks, Connect for marketplace splits     | PayPal (worse developer experience), Adyen (enterprise pricing)                            |

    **Architecture Diagram** (use Mermaid). Include failure boundaries -- show where retries, circuit breakers, or dead letter queues live:

    ```mermaid theme={null}
    flowchart LR
      Client --> CDN --> LoadBalancer
      LoadBalancer --> API1 & API2
      API1 & API2 --> Redis[(Redis)]
      API1 & API2 --> DB[(PostgreSQL)]
      API1 --> Queue[RabbitMQ]
      Queue --> Workers
      Queue --> DLQ[Dead Letter Queue]
    ```

    <Warning>
      A diagram without failure boundaries is incomplete. If your diagram only shows the happy path, add at least one error flow -- for example, what happens when the message queue is unreachable, or when a worker crashes mid-job.
    </Warning>
  </Step>

  <Step title="Key Features" icon="star">
    **Purpose**: Show depth in each domain you built. Do not list features like a product spec -- explain the engineering decisions behind them.

    Group by domain. For each feature, briefly note the technical approach and any non-obvious decision:

    **Authentication and Authorization**

    * JWT with refresh token rotation -- short-lived access tokens (15 min) with rotating refresh tokens stored in HttpOnly cookies. Chose this over session-based auth because horizontal scaling with sticky sessions adds load balancer complexity.
    * Role-based access control (Buyer, Seller, Admin) -- enforced at the API middleware layer, not just the UI. A seller cannot hit admin endpoints even with a valid token.
    * OAuth2 with Google and GitHub -- reduces signup friction. Linked accounts share a single user record to avoid duplicate identity issues.

    **Payments**

    * Stripe Elements for PCI compliance -- keeps card data off our servers entirely, reducing PCI scope from SAQ D to SAQ A.
    * Webhook handling with idempotency keys -- every webhook handler is idempotent so retries do not create duplicate orders.
    * Refund flow with seller approval -- two-phase refund: buyer requests, seller approves, system executes. Added a 48-hour auto-approval timeout to prevent indefinite holds.

    <Tip>
      For each feature, ask yourself: "If an interviewer asked me why I did it this way, could I explain the alternative I rejected and why?" If not, you need to dig deeper before writing it up.
    </Tip>
  </Step>

  <Step title="Flows and Diagrams" icon="arrows-turn-to-dots">
    **Purpose**: Show you can visualize complex interactions. Diagrams are the fastest way for a reviewer to assess your systems thinking.

    Include 2-3 key flows. At minimum:

    * **User Flow**: Happy path for the main use case. This is expected.
    * **System Flow**: How services communicate, including async boundaries.
    * **Error Flow**: How you handle failures. **This is the flow that separates good case studies from great ones.** Most candidates skip it.

    **Happy path -- payment checkout:**

    ```mermaid theme={null}
    sequenceDiagram
      participant User
      participant Frontend
      participant API
      participant Stripe
      participant DB
      
      User->>Frontend: Clicks "Pay Now"
      Frontend->>API: POST /checkout
      API->>Stripe: Create PaymentIntent
      Stripe-->>API: client_secret
      API-->>Frontend: clientSecret
      Frontend->>Stripe: confirmPayment()
      Stripe-->>Frontend: Success
      Frontend->>API: POST /orders/confirm
      API->>DB: Update order status
      API-->>Frontend: Order confirmed
    ```

    **Error path -- what happens when the webhook fails:**

    ```mermaid theme={null}
    sequenceDiagram
      participant Stripe
      participant API
      participant DLQ as Dead Letter Queue
      participant Worker
      participant DB
      
      Stripe->>API: POST /webhooks/stripe (payment_intent.succeeded)
      API->>API: Verify signature, check idempotency key
      API->>DB: Attempt order update
      DB-->>API: Connection timeout
      API->>DLQ: Enqueue failed event
      DLQ->>Worker: Retry after backoff
      Worker->>DB: Retry order update
      DB-->>Worker: Success
    ```

    <Tip>
      **Diagram tip**: Label your arrows with the actual HTTP method and endpoint or message type. "POST /checkout" is far more useful than "API request" -- it lets the reviewer trace the flow against your API design section.
    </Tip>
  </Step>

  <Step title="API and Data Design" icon="database">
    **Purpose**: Show you can design clean interfaces and data models. Do not list every CRUD endpoint -- highlight the interesting design decisions.

    **Important Endpoints** (grouped by bounded context, not by HTTP method):

    ```
    # Products -- note: seller-only writes enforced via RBAC middleware
    GET  /api/products            -- List with filters (category, price range, seller)
    POST /api/products            -- Create product (seller role required)

    # Orders -- note: idempotency key required on POST
    POST /api/orders              -- Create order (idempotency key in header)
    GET  /api/orders/:id          -- Get order details (scoped to user role)
    PATCH /api/orders/:id/status  -- Update status (state machine enforced)

    # Payments -- note: webhook endpoint has no auth, uses signature verification
    POST /api/webhooks/stripe     -- Stripe webhook receiver (signature verified)
    ```

    **Database ERD**:

    ```mermaid theme={null}
    erDiagram
      User ||--o{ Order : places
      Order ||--|{ OrderItem : contains
      Product ||--o{ OrderItem : "included in"
      User ||--o{ Product : sells
    ```

    Explain your normalization decisions alongside the ERD. Where did you denormalize for performance? What consistency risks did that introduce? For example: "We denormalized the seller name into the OrderItem table to avoid a join on the order listing page. This means seller name changes require a background job to update historical orders."

    <Tip>
      **Interview signal**: Grouping endpoints by bounded context (Products, Orders, Payments) instead of by HTTP method (all GETs, all POSTs) signals domain-driven thinking. It also makes your API documentation easier to navigate.
    </Tip>
  </Step>

  <Step title="Challenges and Solutions" icon="lightbulb">
    **Purpose**: This is the most valuable section of your entire case study. It shows your problem-solving ability, and it is the section interviewers and mentors read first.

    Include 5-10 specific challenges. For each one, cover:

    * What was the problem? (Describe the symptom, not just the category.)
    * Why was it hard? (What made the obvious solution insufficient?)
    * What alternatives did you consider? (Show you explored the solution space.)
    * How did you solve it? (Be specific about the approach.)
    * What trade-off did you accept? (Every solution has a cost.)

    | Challenge                                                      | Why It Was Hard                                                                            | Solution                                                                                    | Trade-off                                                                      |
    | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
    | Two buyers purchasing the last item simultaneously             | Race condition between read and write; database-level locks would kill throughput          | Optimistic locking with version numbers on inventory rows                                   | Slight UX friction -- one buyer sees a "sold out" error after clicking "Buy"   |
    | Product search returning results in 3+ seconds on 50K products | Full-text search on PostgreSQL was acceptable at 5K products but degraded at scale         | ElasticSearch with async indexing via a change-data-capture pipeline                        | Added infrastructure complexity and a 2-second indexing delay for new products |
    | Stripe webhook deliveries silently failing for 3 hours         | Webhook endpoint returned 200 but the downstream order update threw an unhandled exception | Idempotent handlers with signature verification, plus a dead letter queue for failed events | 5-minute retry delay on failures; required adding monitoring for DLQ depth     |

    <Warning>
      **Common mistake**: Writing generic challenges like "deployment was difficult." That tells the evaluator nothing. Instead, describe the specific failure: "Our Docker container ran out of memory during builds because the Node.js process exceeded the 512MB default heap size when bundling 200+ product images." Specificity is credibility.
    </Warning>
  </Step>

  <Step title="Best Practices" icon="shield-check">
    **Purpose**: Show you know production-grade engineering. Only claim practices you actually implemented -- evaluators will ask you to elaborate.

    * **Security**: CSRF tokens on state-changing requests, rate limiting (e.g., 100 req/min per IP on auth endpoints), server-side input validation with Joi/Zod schemas on every POST/PATCH endpoint, parameterized queries for SQL injection prevention, bcrypt with cost factor 12 for password hashing. If you used Helmet.js or set specific security headers, mention them.
    * **Performance**: CDN caching for static assets with cache-busting hashes, database indexing on frequently queried columns (run `EXPLAIN ANALYZE` and include the results if they show interesting optimizations), connection pooling with a pool size matched to your expected concurrency, lazy loading for below-the-fold images and code splitting by route.
    * **Developer Experience**: TypeScript for type safety across the stack, ESLint + Prettier with shared config, pre-commit hooks via Husky to prevent broken code from reaching the repo, CI/CD pipeline with automated tests and preview deployments.
    * **Observability**: Structured JSON logging with correlation IDs for request tracing, error tracking with Sentry (including source maps for production), health check endpoints for load balancer probes, and at least basic metrics (request count, latency histogram, error rate).

    <Tip>
      **Credibility test**: For every practice you list, ask yourself -- "If an interviewer said 'walk me through how you implemented this,' could I explain it in detail?" If not, either learn how it works or remove it from your list. Claiming practices you did not implement is worse than having a shorter list.
    </Tip>
  </Step>

  <Step title="Conclusion" icon="flag-checkered">
    **Purpose**: Summarize impact and show growth mindset. This is your chance to demonstrate reflection -- the hallmark of a senior engineer.

    * **Outcomes and Metrics**: Quantify everything you can. "Load time improved 60% (from 2.5s to 1.0s)", "Handled 10K concurrent users at p95 under 200ms", "99.9% uptime over 3 months." If you do not have production metrics, use load test results and be transparent about it.
    * **Learnings -- what would you do differently?**: This is not a weakness section. It shows maturity. Examples: "I would adopt a monorepo with Turborepo from the start instead of splitting repos, which caused versioning headaches." "I would introduce feature flags earlier to decouple deployment from release."
    * **Next Steps**: What features or improvements would you add with more time? Prioritize by impact. Show that you are thinking about the product roadmap, not just the code.

    <Tip>
      **Senior engineer move**: In the "what I would do differently" section, frame your learnings as trade-offs you now understand better. "I chose a monolithic architecture for speed of development. If I were building this for a team of 10+ engineers, I would start with a modular monolith with clear bounded contexts to enable future extraction into services."
    </Tip>
  </Step>
</Steps>

***

## Rubric -- What Mentors and Evaluators Look For

Understanding the rubric before you write is like understanding the test format before an exam. Structure your effort accordingly.

| Criteria                   | Weight | Excellent                                                                                         | Acceptable                                                                      | Needs Work                                                       |
| -------------------------- | ------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| **Clarity of Writing**     | 20%    | Clear, concise, well-organized; a reader can understand the system in 5 minutes                   | Readable but some sections are vague or disorganized                            | Rambling, unclear structure, jargon without explanation          |
| **Technical Depth**        | 30%    | Shows deep understanding of tech choices; can explain the "why" and "what else" for each decision | Describes implementation correctly but does not explain alternatives considered | Surface-level descriptions; "we used X" without reasoning        |
| **Architecture Reasoning** | 30%    | Explains trade-offs, alternatives considered, and failure modes; includes error flow diagrams     | Mentions some trade-offs but misses failure analysis                            | "I used X because it is popular" or no trade-off analysis at all |
| **Evidence**               | 20%    | Diagrams, code references, metrics, live demo or video walkthrough                                | Some diagrams or metrics but incomplete coverage                                | Text-only, no visual proof, no quantitative metrics              |

<Tip>
  **Where to invest your time**: Architecture Reasoning and Technical Depth together account for 60% of the evaluation. If you are short on time, prioritize the "Challenges and Solutions" section and the "Why" column of your tech stack table -- they directly serve both criteria.
</Tip>

***

## Pro Tips

<AccordionGroup>
  <Accordion title="Keep it 4-8 pages -- ruthlessly edit" icon="file-lines">
    Long enough to be comprehensive, short enough to be readable. Link out to code rather than pasting large snippets. A common mistake is including 50 lines of boilerplate code that adds no insight. If a code snippet does not illustrate a decision or trade-off, remove it and link to the file instead.
  </Accordion>

  <Accordion title="Lead with impact, not implementation" icon="chart-line">
    Start each section with WHY it matters, then explain HOW. "Reduced checkout time by 40% by implementing a Redis-backed session cache" is better than "Implemented Redis caching." The impact hooks the reader; the implementation earns their respect.
  </Accordion>

  <Accordion title="Show, do not tell -- visuals beat paragraphs" icon="eye">
    Screenshots, GIFs, architecture diagrams, and Mermaid sequence diagrams beat paragraphs of text every time. A well-labeled architecture diagram with failure boundaries is worth more than a page of prose. If you have a complex flow, diagram it. If you have a performance improvement, show a before/after chart.
  </Accordion>

  <Accordion title="Be honest about trade-offs and mistakes" icon="scale-balanced">
    Saying "MongoDB was wrong for our use case because we underestimated the need for multi-document ACID transactions in our payment flow; we migrated to PostgreSQL in week six" shows engineering maturity, not weakness. Evaluators trust candidates who can identify and correct mistakes far more than candidates who claim everything went perfectly.
  </Accordion>

  <Accordion title="Get feedback before submitting" icon="comments">
    Have a mentor or peer review your case study before submitting. Ask them specifically: "Is there any section where you are confused about why I made a particular decision?" and "Which section feels the weakest?" Fresh eyes catch unclear explanations and unstated assumptions you have internalized.
  </Accordion>

  <Accordion title="Use AI tools strategically for drafting" icon="wand-magic-sparkles">
    Use AI coding assistants (Cursor, Claude Code, Windsurf) to help draft your case study, but do not let them write uncritically. AI tools are excellent at generating structure, suggesting trade-offs you might have missed, and improving clarity. They are poor at inventing authentic challenges you actually faced. Write the Challenges and Solutions section yourself first, then use AI to sharpen the prose and fill gaps.
  </Accordion>
</AccordionGroup>

***

## Ready to Write?

<CardGroup cols={2}>
  <Card title="Template" icon="file" href="/case-studies/template">
    Copy this template and fill in your project details. Every placeholder includes guidance on what belongs there.
  </Card>

  <Card title="Example" icon="star" href="/case-studies/example-multi-vendor">
    See a complete example for reference. Pay special attention to how every technology choice includes a "why" column.
  </Card>
</CardGroup>
