A. Roadmap overview
In 26 weeks (about 310 hours) this roadmap takes you from "I know Java syntax" to being able to open a real Spring Boot service and trace one request through every layer: controller, service, repository, database, cache, Kafka, external calls, threads, JVM, logs, metrics and failures. For each layer you will be able to say why it exists, how it works, what breaks, and how to fix it.
| Item | Plan |
|---|---|
| Duration | 26 weeks (about 6 months) |
| Daily time | 1.5 to 2.5 hours, six learning days plus one review day per week |
| Total | 156 learning days, 26 review days, about 310 hours |
| Structure | 4 levels, 16 phases, 7 projects, 4 level checkpoints |
| Entry point | Basic Java syntax, OOP, collections, exceptions |
| Exit point | Interview-ready for SDE-1 at week 15, SDE-2 at week 26 |
After completing it you can:
- Build a production-style REST API with correct validation, error handling, pagination and idempotency.
- Find why an API got slow: service, SQL, execution plan, index, connection pool or database load.
- Choose transaction boundaries, and explain propagation, isolation and why a self-invoked
@Transactionalmethod does nothing. - Secure an API with Spring Security, JWT and sane access control.
- Run Kafka consumers safely: partitions, offsets, retries, DLQs, idempotent handling.
- Read thread dumps, GC behavior and metrics, and fix pool exhaustion or a runaway CPU.
- Design a system on a whiteboard for 45 minutes and defend the trade-offs.
How to use this roadmap
- Build, don't watch. Every week ends with code in a Git repository. A day with no code and no written explanation did not count.
- Break things on purpose. Each topic has a "force it to fail" step. Failure is where understanding comes from.
- Keep an incident journal. After each debugging task, write three lines: symptom, cause, fix. By week 26 you will have 40+ entries, which is your best interview material.
- Explain out loud. Finish every day by explaining the topic in two minutes without notes. If you can't, repeat tomorrow's first 30 minutes on it.
- Use the official docs as the source of truth. Spring, Hibernate, PostgreSQL and Kafka documentation is what you will use at work. Pick one database (PostgreSQL) and one broker (Kafka) and stay with them.
One deliberate deviation from the narrative order
Your narrative lists messaging before concurrency. This roadmap teaches concurrency basics early (week 2) and the deep dive (weeks 16 to 17) before Kafka (weeks 18 to 19). Kafka consumers, thread pools, backpressure and idempotent handlers are hard to reason about without locks, memory visibility and executor behavior. Observability also comes before performance (weeks 20 and 21) because you cannot tune what you cannot measure.
Time budget by level
| Level | Weeks | Share of time | Outcome |
|---|---|---|---|
| 1. Strong Backend Foundations | 1 to 8 | 31% | Java, Spring, REST, SQL |
| 2. Production Backend Engineer | 9 to 15 | 27% | JPA, transactions, testing, security, Docker, caching |
| 3. SDE-2 | 16 to 22 | 27% | Concurrency, Kafka, observability, performance, resilience |
| 4. Advanced Backend Engineer | 23 to 26 | 15% | System design, capstone, interview sprint |
Level 4 is short on purpose. It is the start of a long habit, not a finish line: reliability and architecture skill keeps growing with every service you operate.
B. Complete roadmap
Each phase has the same shape: goal, a week-by-week table, a production scenario, interview questions and exit criteria. Every table row follows the loop learn, understand, code, break it, explain. "Level" in the tables is the interview depth: S1 is expected from an SDE-1, S2 separates an SDE-2.
Level 1: Strong Backend Foundations (weeks 1 to 8)
Phase 1: Java for backend engineering (weeks 1 to 2)
Goal: Know exactly the Java that Spring and production code lean on, and nothing else.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 1 | Collections internals | HashMap buckets, resize, treeification; ArrayList vs LinkedList; HashSet, TreeMap; fail-fast iterators | Wrong collection choice causes most slow service code | Write a toy HashMap; benchmark ArrayList vs LinkedList on 1M operations | S1 |
| 1 | equals, hashCode, immutability | The contract, mutable keys, defensive copies, final, records |
Broken keys silently lose data in maps and caches | Mutate a key inside a HashMap and watch the entry vanish; fix it with a record | S1 |
| 1 | Generics, enums, Optional | Wildcards, type erasure, enums with behavior, Optional only as a return type | You read framework signatures daily | Replace a null-heavy method with Optional; give each enum constant its own behavior | S1 |
| 1 | Lambdas, functional interfaces, streams | map, filter, groupingBy, flatMap; Function, Predicate, Supplier; laziness; when a loop is clearer | Everyday service-layer code | Group 100k orders by customer with streams, then with a loop; compare clarity and speed | S1 |
| 1 | Exceptions | Checked vs unchecked, domain exceptions, try-with-resources, cause chains, never swallow | Base for global error handling in Spring | Design an exception hierarchy for a payment domain | S1 |
| 1 | Date and time API | Instant, ZonedDateTime, Duration, time zones, store UTC | Time zone bugs are classic production incidents | Convert timestamps across zones including a DST change | S1 |
| 2 | JVM memory and class loading | Heap, stack, metaspace, young and old generation, class loaders | Needed to read OutOfMemoryError and StackOverflowError | Trigger both errors on purpose and read the messages | S1 |
| 2 | Garbage collection basics | Generational GC, G1 as default, stop-the-world pauses, GC logs | Pauses appear as latency spikes | Run a leaking program; watch the heap with jcmd and read the GC log | S2 |
| 2 | Threads and executors (intro) | Thread states, synchronized, volatile, ExecutorService, fixed vs cached pools, CompletableFuture basics |
Every web request runs on a pool thread | Create a counter race, fix it with synchronized and AtomicInteger |
S1 |
| 2 | Modern Java 17 and 21 | Records, sealed interfaces, switch expressions, pattern matching, text blocks | Current codebases use these | Rewrite a legacy DTO and enum set with records and sealed types | S1 |
Production scenarios: a cache "forgets" entries after an update (mutable key); a service freezes for 2 seconds every few minutes (GC pause).
Interview questions:
- Concept: How does HashMap work? What happens on collision and on resize?
- Why: Why must equals and hashCode be consistent?
- Internals: What lives in the heap, the stack and metaspace?
- Scenario: Two threads increment a shared counter 1M times each. What is the result, and why?
- Coding: Group a list of orders by status and sum the amounts using streams.
Exit criteria: you can explain HashMap in two minutes, spot a mutable-key bug, read a heap OOM message, and write a stream pipeline without looking anything up.
Phase 2: Spring core and Spring Boot internals (weeks 3 to 4)
Goal: Understand what Spring does at startup and at request time, so annotations stop being magic.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 3 | IoC and dependency injection | Container, constructor vs field injection, why constructor injection wins, qualifiers, scopes | Testability and wiring bugs | Build a tiny DI container with reflection (50 lines), then compare with Spring | S1 |
| 3 | Bean lifecycle | Instantiate, populate, Aware callbacks, BeanPostProcessor, init, destroy | Explains proxies, @PostConstruct, startup failures |
Log every lifecycle stage of one bean; add a BeanPostProcessor | S1/S2 |
| 3 | Component scanning and configuration | @Component, @Configuration, @Bean, conditional beans |
Why a bean is or isn't found | Create NoSuchBeanDefinitionException and a circular dependency, then fix both |
S1 |
| 3 | Boot startup and auto-configuration | SpringApplication.run, starters, @Conditional, the auto-configuration imports file, embedded Tomcat |
Why "it just works" and how to override it | Read the auto-config for DataSource; use --debug to see the conditions report |
S2 |
| 4 | Configuration | Profiles, @ConfigurationProperties, environment variables, property precedence |
Same artifact runs in dev, test and prod | Typed properties class with validation; override via environment variable | S1 |
| 4 | AOP and proxies | JDK vs CGLIB proxies, advice, pointcuts, self-invocation trap | Base of @Transactional, @Async, @Cacheable |
Write a timing aspect; prove self-invocation bypasses it | S2 |
| 4 | Request flow | Filter, DispatcherServlet, HandlerMapping, controller, message converters, thread per request | The map you will use for all debugging | Add a logging filter and an interceptor; print the order they run in | S1/S2 |
| 4 | Logging, events, scheduling, Actuator | SLF4J and Logback, levels, MDC, application events, @Scheduled, health and info endpoints |
Operational basics from day one | Publish an event, add a scheduled job, expose /actuator/health |
S1 |
HTTP request -> Tomcat thread -> Filter chain -> DispatcherServlet -> Interceptor
-> Controller -> Service (proxy) -> Repository -> Database
<- JSON via message converter <- response
Pattern of the week: Proxy (AOP and transactions), Template Method (JdbcTemplate), Factory (bean creation). Each is learned from the problem it solves in Spring, not from a catalog.
Production scenarios: the app fails at startup with a circular dependency; @Transactional appears to be ignored; the wrong profile loads in production.
Interview questions:
- Concept: What is IoC? What is a bean?
- Why: Why prefer constructor injection?
- Internals: How does auto-configuration decide which beans to create?
- Scenario: A method calls another
@Transactionalmethod in the same class. What happens? - Debugging: The app can't find a bean. How do you investigate?
Exit criteria: you can draw the request flow from memory, explain the bean lifecycle, and explain a CGLIB proxy and its self-invocation limit.
Phase 3: REST API engineering (weeks 5 to 6)
Goal: Build APIs another team could safely depend on. Project 1 runs through this phase.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 5 | HTTP and REST | Methods, safe vs idempotent, status codes, headers, content negotiation, resource modeling | Most review comments are about this | Model a bookings API; justify each method and status code | S1 |
| 5 | Controllers and DTOs | Request and response DTOs, never exposing entities, mapping | Decouples API from schema | Separate create, update and response DTOs; add MapStruct or manual mappers | S1 |
| 5 | Validation | Bean Validation, custom validators, field vs business rules | Bad input is the default input | Validate nested objects and return field-level errors | S1 |
| 5 | Error handling | @RestControllerAdvice, RFC 9457 Problem Details, error codes, no stack traces in responses |
Clients depend on predictable errors | One handler mapping every domain exception to a stable error body | S1 |
| 6 | Pagination, sorting, filtering | Offset vs cursor pagination, stable ordering, allowed sort fields | Unbounded lists take services down | Offset endpoint, then a cursor version; explain why offset degrades | S1/S2 |
| 6 | Idempotency and retries | Idempotent methods, idempotency keys for POST, safe retries, timeouts | Networks fail; clients retry | Add an Idempotency-Key header that returns the same result on repeat |
S2 |
| 6 | Versioning and compatibility | URI vs header versioning, additive changes, deprecation, OpenAPI contract | Avoid breaking live clients | Publish OpenAPI; list which changes are breaking | S2 |
| 6 | Rate limiting and timeouts (concept) | Token bucket, 429 and Retry-After, server vs client timeouts | Protects the service and its dependencies | Add a simple in-memory token bucket filter | S2 |
Pattern of the week: Builder (response and test data), Chain of Responsibility (filter chain).
Production scenarios: a client retries a payment POST after a timeout and is charged twice; a list endpoint returns 2 million rows and the service runs out of memory.
Interview questions:
- Concept: PUT vs PATCH vs POST? Which are idempotent?
- Why: Why separate DTOs from entities?
- Scenario: The client times out but the server finished the work. How do you make the retry safe?
- Design: Design the API for creating and listing orders.
- Coding: Write a global exception handler returning a validation error list.
Exit criteria: your API has validation, stable errors, pagination, an OpenAPI document and idempotent creation, and you can defend each status code you return.
Phase 4: SQL and relational database fundamentals (weeks 7 to 8)
Goal: Think in queries and plans, because most backend performance problems end in the database.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 7 | Schema design | Keys, constraints, normalization, when to denormalize, data types, money as integers or decimals | Bad schemas are expensive to fix later | Design the e-commerce schema with constraints, then challenge it | S1 |
| 7 | SQL queries | Inner and outer joins, GROUP BY, subqueries, CTEs, window functions | Daily work, and common interview coding | Solve 25 realistic queries (top N per group, running totals, dedupe) | S1 |
| 7 | Migrations | Flyway or Liquibase, versioned scripts, backward-compatible changes | Schema changes ship with code | Add a column and backfill with zero downtime reasoning | S1/S2 |
| 7 | JDBC and connection pools | Connection, PreparedStatement, SQL injection, HikariCP sizing and leak detection | Pools are a top cause of outages | Write raw JDBC once; exhaust a Hikari pool deliberately and read the timeout | S2 |
| 8 | Indexes | B-tree, composite index and leftmost prefix, covering index, selectivity, write cost | The biggest lever for read speed | Load 5M rows; compare queries before and after an index | S1/S2 |
| 8 | EXPLAIN and optimization | EXPLAIN ANALYZE, seq scan vs index scan, join strategies, row estimates, bad plans |
Turns "slow" into a cause | Fix three deliberately slow queries and record the plan before and after | S2 |
| 8 | Transactions and ACID | Atomicity, isolation levels, MVCC, dirty, non-repeatable and phantom reads | Correctness under concurrency | Reproduce a non-repeatable read with two psql sessions | S1/S2 |
| 8 | Locks and deadlocks | Row locks, SELECT ... FOR UPDATE, lock ordering, deadlock detection |
Appears as random timeouts under load | Create a deadlock with two sessions and fix it by consistent lock ordering | S2 |
Production scenario: "API suddenly becomes slow when traffic increases." Investigate in this order: API latency (p95 and p99), service time, repository call, the SQL actually executed, its execution plan, missing or unused index, pool wait time, and finally database CPU and locks. Write this chain into your incident journal as your first full entry.
Interview questions:
- Concept: What is an index? What are ACID and the isolation levels?
- Why: Why is a composite index order important?
- Internals: How does a B-tree index speed up lookups? What is MVCC?
- Scenario: A query was fast yesterday and slow today. What do you check?
- Debugging: How do you read an
EXPLAIN ANALYZEoutput? - Coding: Second-highest salary per department; find duplicate rows.
Level 1 checkpoint (end of week 8): Project 1 is finished and documented; you can answer the questions above out loud; you have 8 incident-journal entries. If you fail more than two of these, repeat week 7 or 8 before moving on.
Level 2: Production Backend Engineer (weeks 9 to 15)
Phase 5: JPA, Hibernate and Spring transactions (weeks 9 to 11)
Goal: Know what Hibernate does behind your repository calls, and control transaction boundaries on purpose. Project 2 (e-commerce) runs through this phase.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 9 | Persistence context and entity lifecycle | Transient, managed, detached, removed; first-level cache; flush; dirty checking | Explains "I never called save but it updated" | Change a managed entity without save and watch the SQL log; repeat when detached |
S1/S2 |
| 9 | Spring Data JPA | Derived queries, @Query, projections, save semantics (persist vs merge), SQL logging |
Daily repository work | Build repositories for products, orders, customers; turn on SQL logging with bind values | S1 |
| 9 | Mapping and schema | Entity mapping, ID strategies, enums, embeddables, equals/hashCode on entities, Flyway-owned schema |
Wrong mappings cause subtle bugs | Map the schema from week 7; validate with ddl-auto=validate |
S1 |
| 10 | Relationships and fetching | OneToMany, ManyToOne, ManyToMany pitfalls, lazy vs eager, LazyInitializationException, open-session-in-view |
Source of most Hibernate production problems | Trigger a lazy exception; then fix it three different ways | S1/S2 |
| 10 | N+1 queries | Detecting N+1, fetch join, @EntityGraph, batch fetching, DTO projections |
The most famous JPA performance bug | Load 100 orders with items: count queries before and after the fix | S1/S2 |
| 10 | Pagination and batching | Paginating with joins (in-memory pagination warning), keyset pagination, JDBC batch size, IDENTITY disables batching |
Bulk work stalls without it | Insert 100k rows three ways; compare time and statement counts | S2 |
| 11 | @Transactional internals |
Proxy, TransactionInterceptor, transaction manager, connection binding to thread, self-invocation, rollback rules (checked exceptions do not roll back by default) | Wrong boundaries cause lost data or locked connections | Two DB writes in one transaction; fail the second; verify rollback; then call it from inside the class | S1/S2 |
| 11 | Propagation and isolation | REQUIRED, REQUIRES_NEW, NESTED, MANDATORY; isolation vs database defaults; readOnly |
Interview staple and real bug source | Write a test for each propagation type using an audit log that must survive rollback | S2 |
| 11 | Locking | Optimistic (@Version), pessimistic (FOR UPDATE), lost update, retry on conflict |
Inventory and balance updates need it | Two threads buying the last item: reproduce overselling, fix with each locking style | S2 |
Pattern of the week: Strategy (pricing and discount rules in the e-commerce project), Adapter (mapping persistence to domain objects).
Production scenarios: a list endpoint fires 301 queries; the connection pool is exhausted because a transaction wraps a slow HTTP call; two customers buy the last item; a deadlock appears only under load.
Interview questions:
- Concept: What is the persistence context? Lazy vs eager loading?
- Why: Why does Hibernate track dirty entities instead of writing immediately?
- Internals: How does
@Transactionalwork at runtime? Where is the connection held? - Scenario: What happens if a
REQUIRES_NEWmethod fails inside an outer transaction? And if the outer one fails afterward? - Debugging: A page is slow and the SQL log shows hundreds of similar queries. What next?
- Coding: Write a service method that transfers money safely between two accounts.
Exit criteria: you can find and fix an N+1 problem, predict rollback behavior for any propagation setting, and explain why a transaction should never wrap a remote call.
Phase 6: Testing (week 12)
Goal: Write tests that catch real bugs and survive refactoring. Apply them to Project 2 and begin Project 3.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 12 | Unit tests | JUnit 5, parameterized tests, Mockito stubs and verification, test data builders | Fast feedback on business rules | Cover the pricing and stock logic with focused tests | S1 |
| 12 | What not to mock | Do not mock the type under test, value objects, or the database you need to verify | Over-mocking tests the mocks, not the system | Rewrite a mock-heavy test as an integration test and compare confidence | S2 |
| 12 | Slice tests | @WebMvcTest with MockMvc, @DataJpaTest, JSON assertions |
Test one layer fast | Test validation errors and status codes at the controller level | S1 |
| 12 | Integration tests | @SpringBootTest, Testcontainers PostgreSQL, real migrations, transaction behavior |
Catches mapping, SQL and transaction bugs that mocks hide | Test the oversell scenario against a real database | S2 |
| 12 | Test strategy | Unit vs integration vs end-to-end, the test pyramid, flaky tests, contract testing basics | Decides where to spend test effort | Write a one-page test plan for Project 3 | S2 |
| Test type | Scope | Speed | Use it for |
|---|---|---|---|
| Unit | One class, collaborators faked | Milliseconds | Business rules, edge cases |
| Integration | Several real components, real database | Seconds | SQL, mapping, transactions, wiring |
| End-to-end | The whole deployed system | Minutes | A few critical user journeys |
Production scenario: all tests pass but production fails on a database constraint; a test passes alone and fails in the full suite because of shared state.
Interview questions:
- Concept: Unit vs integration vs end-to-end test?
- Why: When would you not use a mock?
- Scenario: Tests are flaky in CI. How do you find the cause?
- Coding: Test a service that calls a repository and an external client.
Exit criteria: Project 2 has fast unit tests, controller slice tests and Testcontainers integration tests for the riskiest flows.
Phase 7: Security for backend engineers (week 13)
Goal: Implement authentication and access control correctly, and avoid the common API vulnerabilities.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 13 | Authentication vs authorization | Identity vs permission, sessions vs tokens, stateless trade-offs | Foundation for every design choice | Draw both flows for the same login | S1 |
| 13 | Spring Security internals | SecurityFilterChain, authentication manager, SecurityContext, method security |
Where a request is accepted or rejected | Print the filter chain; add a custom filter in the right position | S2 |
| 13 | Passwords and JWT | BCrypt or Argon2, salting, JWT structure, signature, exp, aud, algorithm checks, refresh tokens, revocation limits |
Most common auth implementation | Build login, access and refresh tokens; reject tampered and expired tokens | S1/S2 |
| 13 | OAuth2 basics | Authorization code with PKCE, resource server, scopes, validating tokens from an identity provider | Used by almost every company | Protect an API as an OAuth2 resource server | S2 |
| 13 | Access control | Roles vs permissions, object-level checks, IDOR/BOLA | The most common real API vulnerability | Prove user A can read user B's order, then fix it | S1/S2 |
| 13 | CORS, CSRF, secrets, OWASP | What CORS does and doesn't protect, when CSRF applies (cookie-based sessions), mass assignment, injection, secrets outside the repo | Frequently asked and frequently misconfigured | Add CORS config; run a checklist against Project 3 | S1/S2 |
Production scenarios: a leaked JWT secret in a Git repository; an endpoint returns another user's data when the ID is changed; a login endpoint is attacked with credential stuffing (add rate limiting).
Interview questions:
- Concept: Session vs JWT? Authentication vs authorization?
- Why: Why hash passwords instead of encrypting them? Why salt?
- Internals: What happens inside Spring Security when a request arrives?
- Scenario: How do you log a user out when JWTs are stateless?
- Coding: Secure an endpoint so users see only their own orders.
Exit criteria: Project 3 is protected by JWT or OAuth2, enforces object-level access, and passes your OWASP API checklist.
Phase 8: Production engineering (week 14)
Goal: Package, configure, deploy and roll back a service safely. Only as deep as an SDE-1 or SDE-2 needs it.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 14 | Git and code review | Branching, rebase vs merge, small pull requests, review checklist | Daily team workflow | Review a classmate's or your own pull request with a written checklist | S1 |
| 14 | Docker and Compose | Multi-stage builds, layers, environment configuration, app plus PostgreSQL plus Redis in Compose | "Works on my machine" ends here | Containerize Project 3 with one command to start everything | S1 |
| 14 | CI/CD concepts | Build, test, scan, package, deploy pipeline; fail fast; artifacts | Every change flows through it | Create a pipeline that builds, tests with Testcontainers and publishes an image | S1/S2 |
| 14 | Health, shutdown, rollouts | Liveness vs readiness, graceful shutdown, rolling deployment, expand-contract migrations | Zero-downtime deploys need backward-compatible code | Enable graceful shutdown; prove no request is dropped during a restart | S2 |
| 14 | Config, secrets, feature flags | Twelve-factor configuration, secrets injection, flags for gradual releases | Safe changes in production | Gate a new endpoint behind a flag | S2 |
| 14 | Kubernetes concepts | Pod, Deployment, Service, probes, ConfigMap and Secret, resource limits, autoscaling idea | You will deploy to it, not administer it | Read and explain a Deployment manifest; no cluster administration required | S2 |
Production scenarios: a deployment drops in-flight requests; a new schema change breaks the previous app version still serving traffic; a pod is restarted repeatedly because the liveness probe checks the database.
Interview questions:
- Concept: Liveness vs readiness probe?
- Why: Why do migrations need to be backward-compatible?
- Scenario: How do you roll back a bad deployment that already ran a migration?
- Design: Describe a CI/CD pipeline for a Spring Boot service.
Exit criteria: Project 3 starts with docker compose up, builds in CI, shuts down gracefully, and you can describe how it would roll out in Kubernetes.
Phase 9: Caching and Redis (week 15)
Goal: Add a cache only when it solves a measured problem, and know how it fails. Project 4 is this phase.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 15 | Why and when to cache | Read-heavy data, latency vs consistency, when not to cache (write-heavy, per-user, cheap queries) | Caches add bugs as well as speed | Measure first: profile a slow endpoint and decide whether to cache it | S1/S2 |
| 15 | Redis and its data structures | Strings, hashes, lists, sets, sorted sets, TTL, atomic commands, single-threaded execution, eviction policies | Redis is more than a key-value map | Build a leaderboard with sorted sets and a counter with INCR |
S1/S2 |
| 15 | Caching patterns | Cache-aside, write-through, write-behind, TTL design, invalidation | Interview staple | Implement cache-aside by hand, then with @Cacheable |
S1/S2 |
| 15 | Failure modes | Stampede, penetration, avalanche, hot keys; mitigations: locking, request coalescing, TTL jitter, negative caching | These cause real outages | Reproduce a stampede with 200 concurrent requests, then prevent it | S2 |
| 15 | Spring Cache | @Cacheable, @CacheEvict, key design, serialization, proxy trap on self-invocation |
Convenient, but easy to misuse | Show the self-invocation trap again; fix it | S1/S2 |
| 15 | Distributed caching | Shared vs local cache, consistency across instances, Redis availability, fallback to the database | Multiple app instances share state | Run two instances; show stale data and fix with invalidation | S2 |
Production scenarios: a popular key expires and the database receives thousands of identical queries; Redis memory fills and evicts the wrong keys; stale prices are shown after an update; Redis becomes the single point of failure.
Interview questions:
- Concept: Cache-aside vs write-through vs write-behind?
- Why: Why can a cache make a system less correct?
- Internals: Why is Redis fast despite being single-threaded for commands?
- Scenario: A hot key expires during peak traffic. What happens and how do you prevent it?
- Design: Design caching for a product-detail page.
Level 2 checkpoint (end of week 15), the SDE-1 line: Projects 1 to 4 are done; you can trace a request through controller, service, repository, SQL and cache; you can explain transactions, N+1, JWT and cache-aside without notes; the journal has 25 or more entries. This is a strong SDE-1 profile. Start SDE-1 mock interviews now and keep going in parallel with Level 3.
Level 3: SDE-2 (weeks 16 to 22)
Phase 10: Concurrency in depth (weeks 16 to 17)
Goal: Reason about shared state, thread pools and blocking, so you can explain why a service stalls under load.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 16 | Java Memory Model | Visibility, happens-before, volatile, safe publication |
Explains bugs that "only happen in production" | Show a thread never seeing a non-volatile flag change | S2 |
| 16 | Locks and synchronization | synchronized, ReentrantLock, ReadWriteLock, lock ordering, deadlock, livelock, starvation |
Shared mutable state needs discipline | Write a deadlock, capture it with jcmd Thread.print, fix it |
S2 |
| 16 | Atomics and concurrent collections | AtomicLong, CAS, ConcurrentHashMap, BlockingQueue, LongAdder |
Lock-free counters and producer-consumer hand-offs | Build a bounded producer-consumer queue and a metrics counter | S2 |
| 16 | ThreadPoolExecutor internals | Core and max size, queue types, rejection policies, why unbounded queues hide overload | The core of most scaling incidents | Overload a pool; observe queue growth and each rejection policy | S2 |
| 16 | Pool sizing | CPU-bound vs IO-bound, Little's Law (concurrency = throughput x latency), Tomcat's default 200 threads | Right-sizing instead of guessing | Size pools for a given latency and throughput; verify with a load test | S2 |
| 17 | CompletableFuture | supplyAsync, thenCompose, allOf, timeouts, exception handling, which executor runs the stage |
Parallel calls to downstream services | Call three fake services in parallel with a timeout and a fallback | S2 |
| 17 | Spring @Async and executors |
Executor configuration, proxy trap, losing MDC and security context across threads | Async that silently breaks logging and security | Configure a named executor and propagate correlation IDs | S2 |
| 17 | Virtual threads (Java 21) | What they are, why blocking IO becomes cheap, enabling in Spring Boot 3.2+, pinning with synchronized, why pool sizing changes |
Hot topic; changes how you size blocking services | Run the same IO-heavy endpoint on platform and virtual threads; compare under load | S2 |
| 17 | Thread dumps and diagnosis | Reading jstack output, blocked vs waiting vs runnable, finding the lock holder |
The tool for "service is hung" | Hang an app on purpose; diagnose from three dumps taken 5 seconds apart | S2 |
Pattern of the week: Observer (event publishing and Kafka consumers), Decorator (context-propagating executor wrapper), Singleton (and why Spring scopes replace hand-written singletons).
Production scenarios: every request hangs and CPU is idle (all pool threads blocked on one slow call); an async job loses the user's identity; a deadlock after a harmless-looking change in lock order.
Interview questions:
- Concept:
synchronizedvsReentrantLock? What doesvolatileguarantee? - Why: Why not use an unbounded queue in a thread pool?
- Internals: How does
ThreadPoolExecutordecide between queueing and creating a thread? - Scenario: CPU is at 5% but requests time out. What do you check?
- Debugging: How do you find a deadlock in a running service?
- Coding: Implement a thread-safe bounded blocking queue.
Exit criteria: you can read a thread dump, size a pool with numbers, and explain when virtual threads help and when they do not.
Phase 11: Messaging, Kafka and asynchronous processing (weeks 18 to 19)
Goal: Build consumers that survive duplicates, failures and restarts. Project 5 is this phase.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 18 | Why asynchronous | Decoupling, smoothing spikes, queue vs log, cost of eventual consistency | Decide before reaching for Kafka | List which steps of checkout must be synchronous and which can wait | S1/S2 |
| 18 | Kafka architecture | Topics, partitions, brokers, replication and ISR, retention, log compaction | The mental model for everything else | Run Kafka locally; produce and read messages from the command line | S1/S2 |
| 18 | Producers | Keys and partitioning, acks, idempotent producer, batching with linger.ms, retries |
Ordering and durability are decided here | Send events with and without keys; show ordering per partition only | S2 |
| 18 | Consumers and groups | Consumer groups, partition assignment, offsets and commits, rebalancing, max.poll.interval.ms |
Source of duplicates and stalls | Run 3 consumers; kill one and watch the rebalance | S2 |
| 19 | Delivery semantics | At-most-once, at-least-once, effectively-once, Kafka transactions, why "exactly-once" has limits at the edges | Interview staple, and misunderstood | Make a consumer crash after processing but before commit; show the duplicate | S2 |
| 19 | Idempotent consumers | Deduplication table, upserts, natural idempotency keys | The practical answer to duplicates | Add a processed-events table and prove replays are harmless | S2 |
| 19 | Retries and DLQ | Backoff, retry topics, poison messages, dead-letter topic, replay tooling | One bad message must not block a partition | Inject a poison message; route to a DLT; replay after the fix | S2 |
| 19 | Outbox, lag and backpressure | Transactional outbox, consumer lag, max.poll.records, listener concurrency |
Reliable "save then publish" | Implement the outbox for order created events; measure lag under load | S2 |
| 19 | Jobs and batch | @Scheduled on multiple instances (locking, ShedLock), Spring Batch chunks, restart, skip |
Reports, reconciliations, cleanups | Nightly reconciliation job that runs once across 3 instances | S1/S2 |
Production scenarios: consumer lag grows steadily after a release; one malformed message blocks a partition forever; an order is saved but its event is never published; a rebalance storm because processing exceeds the poll interval.
Interview questions:
- Concept: Partition vs consumer group vs offset?
- Why: Why does Kafka guarantee order only within a partition?
- Internals: What happens during a consumer rebalance?
- Scenario: The consumer processed a message and crashed before committing. What now?
- Debugging: Consumer lag keeps increasing. How do you investigate?
- Design: Design reliable order-created events from a database write to a downstream service.
Exit criteria: Project 5 handles duplicates, poison messages and restarts without losing or double-applying anything, and you can explain delivery semantics honestly.
Phase 12: Observability and production debugging (week 20)
Goal: Debug from symptoms using logs, metrics and traces, not guesses.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 20 | Structured logging | JSON logs, levels, what not to log (secrets, personal data), log volume cost | Searchable logs are the first debugging tool | Switch Project 5 to JSON logs with consistent fields | S1/S2 |
| 20 | Correlation IDs | Generate or accept a request ID, MDC, propagate through HTTP calls, threads and Kafka headers | Follow one request across services | Trace one order from the API to the consumer using a single ID | S2 |
| 20 | Metrics | Micrometer, counters, gauges, timers, percentiles vs averages, the RED and USE methods, label cardinality | Metrics show trends and alert; logs explain | Export latency histograms, pool usage and Kafka lag to Prometheus | S2 |
| 20 | Dashboards and alerts | Prometheus and Grafana concepts, symptom-based alerts, error budget idea, alert fatigue | Alerts should wake you only for user impact | Build one dashboard and two alerts for Project 5 | S2 |
| 20 | Distributed tracing | Spans, trace context propagation, OpenTelemetry via Micrometer Tracing, sampling | Shows where time goes across services | Trace a request through API, database and Kafka; find the slow span | S2 |
| 20 | Health and error monitoring | Actuator health groups, readiness, error tracking tools, grouping exceptions | Know about failures before users report them | Add a custom health indicator; break a dependency and watch readiness change | S1/S2 |
Production scenario: "Users report that checkout is slow." Start with metrics: is p95 or p99 latency up, for which endpoint, since when (a deployment?). Open a trace of a slow request to see which span grew: your service, the database, the cache or an external payment API. Then use the correlation ID to read exactly that request's logs. Check pool usage, error rate and downstream latency to confirm the cause, then fix and write the journal entry.
Interview questions:
- Concept: Logs vs metrics vs traces?
- Why: Why are percentiles better than averages?
- Scenario: Error rate rises but latency is normal. Where do you look?
- Debugging: Walk through investigating a slow checkout.
- Design: What would you monitor for a Kafka consumer service?
Exit criteria: from a single slow request ID you can find the slow component in under 10 minutes using your own dashboards.
Phase 13: Performance and scalability (week 21)
Goal: Reason about latency and capacity with numbers, then investigate bottlenecks in a fixed order.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 21 | Latency, throughput and capacity | p50 vs p99, tail latency, QPS, Little's Law, saturation, queueing | The language of every scaling discussion | Estimate capacity for 2,000 QPS at 80 ms per request | S2 |
| 21 | Load testing | k6 or Gatling, realistic scenarios, warm-up, finding the knee of the curve | Measure before changing anything | Load test Project 4 and find the QPS where p99 breaks 500 ms | S2 |
| 21 | Profiling the JVM | JFR or async-profiler, flame graphs, heap dumps, GC logs, container memory limits | Turns "CPU is high" into a method name | Profile a CPU spike; find the hot method in a flame graph | S2 |
| 21 | Pools and downstream limits | Connection pool vs thread pool vs downstream capacity; sizing the chain | Bottleneck is usually the smallest pool | Show how a pool of 10 caps throughput regardless of app threads | S2 |
| 21 | Serialization, payloads, batching | Jackson cost, payload size, compression, N small calls vs one batch | Hidden CPU and network cost | Cut a response from 800 KB to 80 KB; measure CPU and latency | S2 |
| 21 | Scaling out | Stateless services, load balancing, horizontal vs vertical scaling, backpressure and load shedding | What to do once one instance is not enough | Run 3 instances behind a load balancer; show sticky state breaking it | S2 |
| Symptom | First look | Typical tools | Common causes |
|---|---|---|---|
| API latency suddenly up | Percentile graph, recent deploy, traces | Grafana, tracing | Slow query, new N+1, cold cache, slow dependency |
| CPU at 100% | Which threads and methods | JFR, flame graph, top -H |
Hot loop, regex, serialization, GC thrash |
| Memory keeps growing | Heap after GC trending up | Heap dump, MAT, GC logs | Unbounded cache or map, leaked listeners, large result sets |
| Database connections exhausted | Pool active vs waiting, long transactions | Hikari metrics, pg_stat_activity |
Transaction around a remote call, leaked connection, slow query |
| Thread pool exhausted | Queue size, blocked threads | Thread dump, executor metrics | Blocking IO on a small pool, slow downstream |
| Kafka consumers fall behind | Lag per partition, processing time | Lag metrics, consumer logs | Slow handler, too few partitions, rebalance loops, poison message |
| Redis becomes a bottleneck | Command latency, hot keys, memory | SLOWLOG, INFO, latency monitor |
Large values, hot key, KEYS scan, missing TTLs |
Interview questions:
- Concept: Latency vs throughput? What is tail latency?
- Why: Why can adding more app threads make a system slower?
- Scenario: CPU is 100% after a release. Walk through your investigation.
- Debugging: The heap grows until OutOfMemoryError. How do you find the leak?
- Design: How would you scale an API from 100 to 10,000 QPS?
Exit criteria: you can take any row in the symptom table, name the first three things you check, and show the tool output you would use.
Phase 14: Distributed systems and resilience (week 22)
Goal: Choose between monolith and microservices with reasons, and make service-to-service calls fail safely. Project 6 is this phase.
| Week | Topic | What to learn | Why it matters | Practical task | Level |
|---|---|---|---|---|---|
| 22 | Monolith, modular monolith, microservices | Service boundaries, data ownership, team size, operational cost, when not to split | Most teams should not start with microservices | Draw the boundaries of the e-commerce system as a modular monolith, then justify one extraction | S2 |
| 22 | Calling other services | RestClient or WebClient, connect and read timeouts, connection pooling, error mapping |
Every remote call can hang | Call a slow fake service; set timeouts and observe pool behavior | S1/S2 |
| 22 | Retries and backoff | Exponential backoff with jitter, retry only idempotent calls, retry amplification | Naive retries cause outages | Show a retry storm, then bound it with limits and jitter | S2 |
| 22 | Circuit breakers and bulkheads | Resilience4j, states, thresholds, fallbacks, isolating pools per dependency | One slow dependency must not sink everything | Protect the payment call; verify other endpoints stay healthy | S2 |
| 22 | Distributed transactions | Why 2PC is avoided, saga (orchestration vs choreography), compensation, outbox, eventual consistency | Order, payment and stock cannot share one transaction | Design a saga for order, payment and inventory with compensations | S2 |
| 22 | Event-driven architecture | Events vs commands, event schemas and evolution, ordering and replay | Loose coupling has costs | Version an event schema without breaking an old consumer | S2 |
Production scenarios: the payment provider slows down and every request thread waits; a retry storm after a short outage keeps the dependency down; payment succeeded but the order was never confirmed.
Interview questions:
- Concept: What is a circuit breaker and what are its states?
- Why: Why is a distributed transaction hard? Why is a saga used instead?
- Scenario: Service A calls B which is slow. What protects A?
- Design: Design order, payment and inventory across three services without a distributed transaction.
- Trade-off: When would you not use microservices?
Level 3 checkpoint (end of week 22), the SDE-2 line: Projects 1 to 6 are done; you can debug each symptom in the performance table; you have implemented idempotent consumers, a circuit breaker and distributed tracing; the journal has 40 or more entries. This is the knowledge that separates SDE-2 from SDE-1.
Level 4: Advanced Backend Engineer (weeks 23 to 26)
Phase 15: System design, introduced through problems (weeks 23 to 24)
Goal: Turn the concepts you already used into whiteboard designs. Nothing here is new theory dumped at once: each concept appears when a problem needs it.
Use one framework for every problem: requirements and scale, rough estimates, API, data model, high-level design, deep dive on the hardest part, failure modes, trade-offs.
| Concept | Where you first needed it | What to understand |
|---|---|---|
| Load balancing | Week 21 scaling | L4 vs L7, round robin vs least connections, health checks, sticky sessions and why to avoid them |
| Read replicas | URL shortener | Replication lag, read-your-writes problems, routing reads |
| Sharding basics | Order system | Shard key choice, hot shards, cross-shard queries, resharding pain |
| Caching layers | Week 15 | Browser, CDN, application and database caches; invalidation across layers |
| Queues | Weeks 18 to 19 | Smoothing load, retries, ordering, backpressure |
| CAP and consistency | Payment system | Partition tolerance is not optional; strong vs eventual consistency; where each is acceptable |
| Reliability | Weeks 14 and 22 | Redundancy, failover, SLOs, graceful degradation |
| Rate limiting | Week 6 | Token bucket, sliding window, distributed counters in Redis |
| Day | Problem | Concepts exercised | What you must show |
|---|---|---|---|
| W23 D1 | URL shortener | ID generation, read-heavy caching, replicas, expiry | Estimates for 100M links; collision-free ID strategy |
| W23 D2 | Rate limiter | Token bucket, Redis atomic scripts, per-user vs global limits | Behavior when Redis is down |
| W23 D3 | Notification system | Queues, fan-out, retries, idempotency, provider limits, user preferences | No duplicate sends under retry |
| W23 D4 to D6 | Review and redesign | Redo day 1 to 3 with a stricter interviewer: add failures and 10x load | Written trade-off notes |
| W24 D1 | Order management system | Saga, inventory consistency, outbox, state machine | Valid state transitions and compensation |
| W24 D2 | Payment system | Idempotency, ledger design, reconciliation, consistency over availability | Double-charge prevention end to end |
| W24 D3 | Job scheduler | Distributed locking, leases, at-least-once execution, retry, time-based triggers | Exactly one worker runs a job in the happy path; safe duplicate handling otherwise |
| W24 D4 | Food delivery backend | Geo-queries, matching, real-time updates, event-driven flow | Where strong consistency is needed and where it is not |
| W24 D5 | Stretch: web crawler or search service | Frontier queue, politeness, deduplication; indexing and ranking basics | A design in 40 minutes with clear bottlenecks |
| W24 D6 | Mock design interview | Random problem, 45 minutes, spoken | Recorded and self-reviewed |
Interview questions:
- Design: Design a rate limiter that works across 10 service instances.
- Trade-off: Strong consistency or availability for a payment system, and why?
- Failure: What happens when the cache, the queue or one database replica fails?
- Scaling: Your design works at 1,000 QPS. What breaks first at 100,000 QPS?
Exit criteria: you can complete a 45-minute design for any problem in this phase, estimate numbers out loud, and name the first bottleneck and the first failure.
Phase 16: Capstone, hardening and interview sprint (weeks 25 to 26)
Goal: Combine everything in one system, break it deliberately, and practice explaining it. Project 7 is this phase.
| Week | Focus | Tasks |
|---|---|---|
| 25 | Build the capstone | Services, schema, events, caching, security, CI, Docker Compose, dashboards (details in section E) |
| 26 D1 to D2 | Failure drills | Kill Kafka, slow the database, expire hot cache keys, exhaust a pool; document what happened and fix it |
| 26 D3 | Load and capacity test | Find the breaking point; write the capacity note |
| 26 D4 | Architecture write-up | A 3-page design document with diagrams, trade-offs and a runbook |
| 26 D5 to D6 | Mock interviews | One SDE-2 coding and debugging round, one design round, with the incident journal as source material |
Exit criteria: the capstone survives your failure drills, and you can explain any component of it for 10 minutes without notes.
Design patterns taught in context
Patterns are taught only through a problem: a naive solution, why it hurts, then the pattern and its trade-off.
| Pattern | Naive solution and its problem | Pattern fix | Where it appears |
|---|---|---|---|
| Strategy | A growing if/else for discount types; every new rule edits one big method |
One interface per rule, chosen at runtime | Pricing in Project 2; payment providers |
| Factory | new calls spread through code and tied to concrete classes |
One place decides which implementation to build | Notification channels; Spring bean creation |
| Builder | Constructors with 9 parameters, easy to misorder | Named steps that build an immutable object | Test data, API responses |
| Adapter | Business code depends on a vendor's API shape | A thin wrapper exposing your own interface | Payment and email providers |
| Decorator | Subclass explosion to add logging, metrics or retries | Wrap an object with the same interface | Context-propagating executors; client wrappers |
| Observer | One service directly calls five others after an event | Publish an event; listeners subscribe | Spring events, Kafka consumers |
| Template Method | Copy-pasted flow with small variations | Fixed skeleton, overridable steps | JdbcTemplate, batch jobs |
| Chain of Responsibility | One method does auth, logging, validation and routing | A pipeline of small handlers | Servlet filters, Spring Security filters |
| Proxy | Cross-cutting code mixed into business methods | A stand-in that adds behavior around calls | @Transactional, @Cacheable, lazy loading |
| Singleton | Hand-written global state that is hard to test | Container-managed single instance; know its thread-safety needs | Spring default bean scope |
The trade-off for every one is the same question: does it remove real duplication or add layers nobody needs yet?
Schedule at a glance
| Phase | Topic | Weeks | Learning days | Project |
|---|---|---|---|---|
| 1 | Java for backend | 1 to 2 | 12 | |
| 2 | Spring core and Boot internals | 3 to 4 | 12 | |
| 3 | REST API engineering | 5 to 6 | 12 | Project 1 |
| 4 | SQL and databases | 7 to 8 | 12 | Project 1 extended |
| 5 | JPA, Hibernate, transactions | 9 to 11 | 18 | Project 2 |
| 6 | Testing | 12 | 6 | Project 2 tests, Project 3 starts |
| 7 | Security | 13 | 6 | Project 3 |
| 8 | Production engineering | 14 | 6 | Project 3 finished |
| 9 | Caching and Redis | 15 | 6 | Project 4 |
| 10 | Concurrency in depth | 16 to 17 | 12 | |
| 11 | Messaging, Kafka, batch | 18 to 19 | 12 | Project 5 |
| 12 | Observability | 20 | 6 | Added to Project 5 |
| 13 | Performance and scalability | 21 | 6 | Load test Project 4 and 5 |
| 14 | Distributed systems and resilience | 22 | 6 | Project 6 |
| 15 | System design | 23 to 24 | 12 | |
| 16 | Capstone and interview sprint | 25 to 26 | 12 | Project 7 |
Revision cycles
| Cycle | When | What you do |
|---|---|---|
| Daily | End of every learning day | Two-minute spoken explanation, one flashcard added |
| Weekly | Day 7 of each week | 60 minutes re-reading the incident journal; 30 minutes answering the week's interview questions out loud; 30 minutes cleaning up the code |
| Spaced recall | 3 days, 1 week and 3 weeks after each topic | Five flashcards or a rebuilt snippet from memory |
| Level checkpoint | Ends of weeks 8, 15, 22 and 26 | Closed-book questions, one live debugging task, one design question; repeat the weakest topic before moving on |
C. Topic dependency graph
[embedded content: topic dependencies · 4 tracks, 20 topics]
Read each column top to bottom: a topic needs the one above it. The bottom row shows the distributed-systems skills that feed system design, and the arrows between them show how failure handling, sagas, outbox and safe consumers connect.
The dependencies that matter most, and the week each is taught:
- Collections and exceptions (week 1) then Spring and proxies (week 4) then
@Transactionaland@Cacheableinternals (weeks 11 and 15). - SQL, indexes and
EXPLAIN(weeks 7 and 8) then JPA and N+1 (week 10) then transactions and locking (week 11) then sagas and outbox (week 22). - Threads and executors (week 2) then locks and the memory model (week 16) then pools, futures and virtual threads (week 17) then Kafka consumers (week 18) then idempotent consumers and distributed processing (week 19).
- JVM memory and GC (week 2) plus logs, metrics and traces (week 20) then profiling and scaling (week 21).
- REST and timeouts (weeks 5 and 6) then retries, circuit breakers and bulkheads (week 22).
- Git, Docker and CI (week 14) before anything you need to run on more than one instance: caching with Redis (week 15) and Kafka (week 18).
D. SDE-1 vs SDE-2 boundary
An SDE-1 delivers a well-defined feature correctly inside an existing service. An SDE-2 owns a feature or service end to end, finds the cause of a production problem without being led to it, and explains the trade-offs of a design. The boundary is not more topics; it is depth, ownership and judgment. Week 15 is the SDE-1 line and week 22 is the SDE-2 line.
| Area | Expected from SDE-1 (by week 15) | What SDE-2 adds (by week 22) |
|---|---|---|
| Scope | Completes a clear task with guidance; asks good questions | Takes an ambiguous problem, breaks it down, delivers across several tasks |
| Java | Collections, streams, exceptions, equals and hashCode, records | Memory model, GC behavior, reads a thread dump and a heap dump |
| Spring | Builds controllers, services, repositories; knows DI and bean lifecycle | Explains proxies, auto-configuration and startup; debugs wiring and AOP issues |
| APIs | Correct REST design, DTOs, validation, error handling | Idempotency, pagination at scale, versioning, backward compatibility, rate limiting |
| Database | Writes joins and indexes; knows ACID and isolation levels | Reads execution plans, fixes N+1, picks locking strategies, reasons about deadlocks and pool sizing |
| Transactions | Uses @Transactional and knows rollback rules |
Chooses boundaries and propagation deliberately; avoids remote calls inside transactions |
| Testing | Unit tests with Mockito, controller and repository tests | Testcontainers integration tests, test strategy, knows what not to mock |
| Security | Implements JWT login and role checks | Object-level access control, OAuth2 resource server, threat thinking on a new endpoint |
| Caching | Cache-aside with Redis and TTL | Stampede, hot keys, invalidation strategy, when not to cache |
| Concurrency | Understands threads, executors and synchronized |
Sizes pools with numbers, chooses between platform and virtual threads, avoids deadlocks |
| Messaging | Produces and consumes Kafka messages | Delivery semantics, idempotent consumers, DLQs, lag diagnosis, outbox |
| Distributed systems | Calls other services with timeouts | Circuit breakers, retry budgets, sagas, consistency trade-offs, microservices judgment |
| Debugging | Reads logs and a stack trace; reproduces locally | Investigates from metrics to traces to logs; forms and tests hypotheses in production |
| Design | Designs a small service with guidance | Leads a whiteboard design with estimates, failure modes and trade-offs |
| Ownership | Delivers reliably; writes clear pull requests | Writes design notes and runbooks; mentors; considers operations, cost and deployment safety |
How to tell which side you are on
You are in SDE-2 territory when you can do all of these without help:
- Given "the API is slow", you name the first three places to look and the tool for each.
- Given a design, you list the failure modes before anyone asks.
- Given a transaction or a consumer, you state what happens on a crash at every step.
- Given a technology choice (Kafka vs a database queue, cache vs no cache), you give two reasons against your own preference.
- Given a number (traffic, data size), you estimate capacity and the likely bottleneck.
If two or more of those are still hard, repeat the related Level 3 phase before attempting SDE-2 interviews.
E. Projects
None of these is a CRUD app. Each project adds one new class of real backend problem, and each must ship with tests, a README, an architecture sketch and incident-journal entries. Keep every project in one Git repository with small, reviewable commits.
| Project | Weeks | New class of problem it introduces |
|---|---|---|
| 1. Meeting-room booking API | 5 to 8 | Correct API design, conflicting bookings, idempotent creation |
| 2. E-commerce backend | 9 to 12 | Hibernate behavior, transactions, overselling, N+1 |
| 3. Order and payment workflow | 12 to 14 | State machines, unreliable external calls, webhooks, security, CI |
| 4. Redis caching and high-traffic API | 15 | Read scaling, cache failure modes, load testing |
| 5. Kafka asynchronous processing system | 18 to 19 | Duplicates, retries, poison messages, outbox |
| 6. Distributed notification system | 22 | Multi-service resilience, priorities, provider failure |
| 7. Ticket-booking platform (capstone) | 25 to 26 | Everything together under a traffic spike |
Project 1: Meeting-room booking API (weeks 5 to 8)
| Aspect | Specification |
|---|---|
| Requirements | Create rooms; book a room for a time range; no overlapping bookings for the same room; cancel; list bookings with filters and pagination |
| APIs | POST /rooms, GET /rooms?minCapacity=&page=, POST /bookings (with Idempotency-Key), GET /bookings?roomId=&from=&to=&cursor=, DELETE /bookings/{id} |
| Database schema | rooms(id, name, capacity), users(id, email), bookings(id, room_id, user_id, start_at, end_at, status, created_at), a unique idempotency_keys(key, response) table; an exclusion constraint or locking to prevent overlap; index on (room_id, start_at) |
| Architecture | Layered monolith: controller, service, repository; PostgreSQL; Flyway migrations |
| Technologies | Spring Boot, Spring Data JPA or JDBC, Bean Validation, Flyway, PostgreSQL, OpenAPI |
| Key decisions | Store UTC; DTOs not entities; one error format; where overlap is enforced (database constraint beats a check-then-insert in code); offset vs cursor pagination |
| Failure scenarios | Two users book the same slot at the same moment; client retries a timed-out POST; invalid time ranges; clock and time zone mistakes |
| Scaling challenges | Booking list slows as data grows; a missing composite index; unbounded date ranges |
| Testing | Unit tests for time-range rules; MockMvc tests for status codes and error bodies; a concurrent booking test |
| Observability | JSON logs with a request ID; /actuator/health; log the SQL of one slow endpoint and fix it with an index |
| Explain in an interview | The request flow through every layer; how you prevent double booking; how idempotency works; why you chose your pagination style |
Project 2: E-commerce backend (weeks 9 to 12)
| Aspect | Specification |
|---|---|
| Requirements | Catalog with search and filters; cart; place an order; inventory decrement; order history; discount rules |
| APIs | GET /products?category=&q=&page=, POST /cart/items, POST /orders, GET /orders/{id}, GET /customers/{id}/orders |
| Database schema | products, inventory(product_id, available, version), carts, cart_items, orders, order_items (with a price snapshot), customers, discounts |
| Architecture | Modular monolith with catalog, cart, order, inventory packages; modules talk through service interfaces, not each other's tables |
| Technologies | Spring Boot, JPA/Hibernate, PostgreSQL, Flyway, Testcontainers |
| Key decisions | Money as integer minor units or BigDecimal, never double; price snapshot in order items; optimistic vs pessimistic locking for stock; transaction boundary for placing an order; fetch strategy per use case |
| Failure scenarios | Overselling the last item; order saved but stock not decremented; LazyInitializationException in serialization; a deadlock when two orders lock items in a different order |
| Scaling challenges | Catalog search under load; N+1 on order history; hot inventory rows during a sale |
| Testing | Unit tests for discount strategies; Testcontainers test with 50 concurrent buyers for 10 items; test that asserts the number of SQL statements for order history |
| Observability | Log SQL statement count per request; a metric for order placement time and stock conflicts; explain-plan notes for the 3 slowest queries |
| Explain in an interview | Where your transaction starts and ends and why; the N+1 you found and how you fixed it; how you made overselling impossible |
Project 3: Order and payment workflow (weeks 12 to 14)
| Aspect | Specification |
|---|---|
| Requirements | Pay for an order through an unreliable payment provider (a small separate Spring app you write with random delays and failures); handle webhooks; protect everything with JWT; run with Docker Compose; build in CI |
| APIs | POST /orders/{id}/pay (idempotent), POST /webhooks/payment (signature verified), GET /orders/{id}, POST /auth/login |
| Database schema | payments(id, order_id, provider_ref, status, amount, idempotency_key unique), payment_events(provider_event_id unique), order_status_history; order states: CREATED, PAYMENT_PENDING, PAID, PAYMENT_FAILED, CANCELLED, FULFILLED |
| Architecture | Order monolith plus a simulated payment provider; calls with connect and read timeouts; webhooks reconcile final state; a scheduled job resolves payments stuck in pending |
| Technologies | Spring Security, JWT, RestClient, Testcontainers, Docker Compose, GitHub Actions or similar |
| Key decisions | Record intent first, call the provider outside any database transaction, update after; validate every state transition; verify webhook signatures; treat webhooks as duplicate-prone and out-of-order |
| Failure scenarios | Provider times out but charged the customer; duplicate webhook; webhook arrives before the API response; application crashes between the provider call and the status update; a user pays another user's order |
| Scaling challenges | Webhook bursts; a backlog of pending payments after a provider outage |
| Testing | Provider failure simulations; duplicate and reordered webhook tests; security tests for object-level access; a full flow integration test in CI |
| Observability | Metrics for payment success rate and provider latency; correlation ID from the API call to the webhook; an alert when payments stay pending longer than a threshold |
| Explain in an interview | How you prevent a double charge end to end; why no transaction wraps the provider call; how reconciliation repairs stuck payments |
Project 4: Redis caching and high-traffic API (week 15)
| Aspect | Specification |
|---|---|
| Requirements | A read-heavy product-detail API behind a cache; price changes invalidate the cache; a "top products" ranking; per-API-key rate limiting. Set your own target (for example p99 under 200 ms) and measure against it |
| APIs | GET /products/{id}, PUT /products/{id}/price, GET /products/top, any endpoint with 429 and Retry-After |
| Database schema | Reuse Project 2 tables; add a product_views counter flushed from Redis periodically |
| Architecture | Two app instances behind a load balancer (nginx), one Redis, PostgreSQL; cache-aside with a local in-process tier for the hottest keys |
| Technologies | Spring Data Redis or Spring Cache, Redis sorted sets and INCR, nginx, k6 or Gatling |
| Key decisions | Key naming; TTL with jitter; serialization format; stampede protection; negative caching for missing products; what happens when Redis is down (serve from the database with a protective limit) |
| Failure scenarios | Hot key expires under load; Redis unavailable; stale price after an update; both instances disagree because one holds a local copy |
| Scaling challenges | One flash-sale product receives most traffic; Redis memory and eviction; a cold cache after restart |
| Testing | Redis Testcontainer; a test with 100 concurrent requests that asserts only one database load; a Redis-down test |
| Observability | Cache hit ratio, database queries per second, Redis latency and evictions; before and after load-test graphs |
| Explain in an interview | The measured before and after numbers; why you chose that TTL; what happens to the database if Redis dies at peak |
Project 5: Kafka asynchronous processing system (weeks 18 to 19)
| Aspect | Specification |
|---|---|
| Requirements | Orders publish events reliably; an invoice consumer and an inventory consumer process them independently; failures retry and then land in a dead-letter topic; an admin can replay; a nightly Spring Batch job reconciles orders and invoices |
| APIs | POST /orders (from Project 3), GET /orders/{id}/status, POST /admin/dlt/replay |
| Database schema | outbox_events(id, aggregate_id, type, payload, created_at, published_at), processed_events(consumer, event_id) with a composite primary key, invoices |
| Architecture | Order service writes the order and an outbox row in one transaction; a poller publishes to the orders.v1 topic keyed by order ID; two consumer groups; retry then dead-letter topics |
| Technologies | Spring Kafka, Kafka (local or Testcontainers), Spring Batch, ShedLock for scheduled jobs |
| Key decisions | Message key and partition count; acks=all with the idempotent producer; event schema with a version field; retry and backoff policy; what counts as a poison message |
| Failure scenarios | Consumer crashes after processing but before commit; broker unavailable during publish; duplicate delivery; malformed message; rebalance in the middle of processing |
| Scaling challenges | Consumer lag when a handler is slow; adding consumers beyond the partition count does nothing; a hot partition from a skewed key |
| Testing | Duplicate-delivery test proving no double effect; dead-letter test; outbox crash test (kill the poller mid-batch) |
| Observability | Lag per consumer group, handler duration, dead-letter count with an alert, one trace spanning the HTTP call, the publish and the consume |
| Explain in an interview | How you avoid losing or double-applying an event; the difference between at-least-once and effectively-once; how you investigated growing lag |
Project 6: Distributed notification system (week 22)
| Aspect | Specification |
|---|---|
| Requirements | Send email, SMS and push (simulated providers) according to user preferences; priorities (a one-time password must not wait behind a marketing campaign); retries with backoff; per-provider rate limits; scheduled sends; delivery status; bulk campaigns |
| APIs | POST /notifications (idempotent), POST /campaigns, GET /notifications/{id}, PUT /users/{id}/preferences |
| Database schema | notifications(id, user_id, channel, template_id, status, idempotency_key, scheduled_at, attempts), delivery_attempts, preferences, templates |
| Architecture | Notification API, separate Kafka topics per priority, channel workers calling providers through circuit breakers, a scheduler for due messages, Redis for rate limits and deduplication, PostgreSQL for state |
| Technologies | Spring Boot, Kafka, Redis, Resilience4j, Docker Compose, OpenTelemetry |
| Key decisions | Topic per priority to avoid head-of-line blocking; a bulkhead and a rate limit per provider; retry budget; dedupe key sent to the provider; fallback channel when a provider is down; manual replay for dead letters |
| Failure scenarios | Provider outage; the same message sent twice after a retry; a campaign floods the workers and delays one-time passwords; a worker dies mid-send |
| Scaling challenges | A campaign to 1 million recipients (fan-out and backpressure); provider rate limits that are lower than your throughput |
| Testing | Contract tests between the API and workers; fault injection for each provider; a test showing high-priority messages stay fast during a campaign |
| Observability | Success rate and latency per channel; queue age per priority; circuit breaker state; traces from request to provider call |
| Explain in an interview | How you guarantee priority, how you avoid duplicate sends, and what happens when a provider is down for an hour |
Project 7: Ticket-booking platform, the SDE-2 capstone (weeks 25 to 26)
This project is chosen because it combines high contention on limited stock, a traffic spike, payments and notifications.
| Aspect | Specification |
|---|---|
| Requirements | Browse events; hold seats for a few minutes; pay; receive tickets and a notification; seat holds expire; admins see sales reports; role-based access; a waiting room when demand spikes |
| APIs | GET /events, GET /events/{id}/seats, POST /holds, POST /orders (idempotent), POST /webhooks/payment, GET /tickets, GET /admin/reports/sales |
| Database schema | events, seats(event_id, seat_no, status), holds(id, seat_id, user_id, expires_at) with a unique constraint on active holds, orders, payments, tickets, outbox_events, processed_events |
| Architecture | Modular monolith (catalog, booking, payment) plus a separate notification worker consuming Kafka; Redis for the event cache, rate limits and the waiting room; PostgreSQL as the source of truth; Docker Compose; CI pipeline |
| Technologies | Everything from this roadmap: Spring Boot 3 on Java 21, JPA, Flyway, Spring Security with JWT or OAuth2, Redis, Kafka, Resilience4j, Micrometer, OpenTelemetry, Testcontainers, k6 |
| Key decisions | Seat locking strategy (unique constraint, SELECT ... FOR UPDATE SKIP LOCKED, or optimistic version); hold expiry design; why a modular monolith first; platform vs virtual threads; outbox for events; idempotency for payment; what to cache and for how long |
| Failure scenarios | Payment succeeds after the hold expired; double booking under concurrency; Kafka or Redis down; the provider webhook arrives twice or late; a deployment during an on-sale |
| Scaling challenges | A 50x traffic spike at on-sale time; a hot event key; connection pool sizing; sudden lag in the notification worker |
| Testing | Unit tests for hold rules; Testcontainers tests for booking and outbox; a test with 500 buyers for 100 seats that asserts zero oversell; contract test for the event schema; failure drills |
| Observability | Dashboards for booking funnel, p99 latency, pool usage and consumer lag; an invariant checker that alerts on any oversold seat; traces for the full purchase path |
| Deliverables | README with an architecture diagram; three short design decision records; a runbook for the top five failures; a load-test report with the breaking point; your incident journal |
| Explain in an interview | A 15-minute walkthrough: request path, data model, concurrency control, failure handling, scaling plan, and three trade-offs you would revisit |
F. Interview preparation
Interview preparation is built into every phase through the question lists in section B. This section shows how those questions map to what interviewers expect at each level, and how to answer them.
Seven question types, and how to answer each
| Type | Interviewer's goal | How to answer | Example |
|---|---|---|---|
| Concept | Do you know the term? | One-sentence definition, then one concrete example | What is a persistence context? |
| Why | Do you know the motivation? | State the problem it solves and what you'd do without it | Why use connection pools? |
| Internals | Did you look under the hood? | Walk the runtime sequence step by step | How does @Transactional work? |
| Scenario | Can you predict behavior? | State assumptions, trace the outcome, name the edge case | The consumer crashes before commit. What happens? |
| Debugging | Can you investigate calmly? | Start from the symptom, name the first three checks and the tools, then narrow | CPU is 100% after a release |
| Design | Can you make trade-offs? | Clarify requirements, estimate, sketch, deep dive, failures | Design a rate limiter |
| Coding | Can you write correct code? | Clarify, write simply, test with an edge case, discuss complexity or thread-safety | Thread-safe bounded queue |
A reusable answer shape: what it is, why it exists, how it works, what can go wrong, and the trade-off. Practicing this shape on every topic is what turns memorized facts into engineering explanations.
Typical rounds by level
| Round | SDE-1 | SDE-2 |
|---|---|---|
| Java and Spring | Collections, OOP, exceptions, DI, REST, annotations with reasons | Concurrency, JVM, proxies, auto-configuration, transaction internals |
| Database | Joins, indexes, normalization, ACID | Query plans, isolation anomalies, locking, deadlocks, pool exhaustion |
| Project deep dive | Explain your project and your own contribution | Defend decisions, failure handling, scaling, what you would change |
| Debugging or scenario | Read a stack trace, fix a bug | Investigate a production symptom from metrics, traces and logs |
| Low-level design | Design classes for a small system | Design with concurrency, extensibility and testability in mind |
| High-level design | Rare, or a simple service | Full design with estimates, data, failures and trade-offs |
| Behavioral | Learning, teamwork | Ownership, incident handling, disagreement, mentoring |
Concept to interview map
| Concept (phase) | An SDE-1 question | An SDE-2 question |
|---|---|---|
| HashMap (1) | How does HashMap work? | What changes in a concurrent setting, and when is ConcurrentHashMap not enough? |
| Beans and proxies (2) | What is dependency injection? | Why does a self-invoked @Transactional method not start a transaction? |
| REST (3) | PUT vs PATCH? | How do you make a payment endpoint safe to retry? |
| Indexes (4) | What is an index? | Why is this composite index not used? Read this plan. |
| JPA (5) | Lazy vs eager loading? | You see 300 queries on one page. Find and fix it. |
| Transactions (5) | What are ACID properties? | Predict the result of nested REQUIRES_NEW with an outer rollback. |
| Testing (6) | Unit vs integration test? | What do you not mock and why? How do you test a Kafka consumer? |
| Security (7) | Session vs JWT? | How do you revoke a JWT? How do you prevent IDOR? |
| Docker, CI/CD (8) | What does a Dockerfile do? | How do you deploy a schema change with zero downtime? |
| Caching (9) | Cache-aside? | A hot key expires under load. What happens and how do you prevent it? |
| Concurrency (10) | synchronized vs volatile? |
Size a thread pool for 500 QPS at 200 ms. Why might virtual threads change it? |
| Kafka (11) | What is a consumer group? | Lag keeps growing. Investigate. How do you avoid duplicate effects? |
| Observability (12) | Logs vs metrics? | Checkout is slow. Walk me through your investigation. |
| Performance (13) | What is latency vs throughput? | Memory grows until OOM. What is your plan? |
| Resilience (14) | What is a timeout? | Design the call to a slow payment provider so it cannot take your service down. |
| System design (15) | Rarely asked | Design a notification system for 10 million users. |
Interview preparation schedule
| When | Activity |
|---|---|
| Weeks 1 to 15 | Answer each phase's questions out loud on the review day; keep the incident journal |
| Week 15 | Two SDE-1 mock interviews: Java and Spring round, project walkthrough |
| Weeks 16 to 22 | Add debugging drills: one "symptom to cause" exercise per week |
| Weeks 23 to 24 | One recorded mock design interview per week |
| Week 26 | Two full SDE-2 mocks, then apply; schedule a mock every week while interviewing |
A note on data structures and algorithms: most SDE-1 and SDE-2 loops still include coding rounds. This roadmap does not teach them, so budget 30 to 45 minutes on non-daily days or alongside Level 1 and 2. See section I.
G. Daily learning framework
Every learning day follows one loop: Learn, Understand, Code, Debug or Think, Review. The 156 learning days are numbered 1 to 156; the 26 weekly review days are numbered R1 to R26. Roughly one row of a section B table becomes one or two days.
The daily loop
| Step | Purpose | Time at 2 hours | Time at 1.5 hours |
|---|---|---|---|
| Learn | Read the official docs or one focused source; no video marathons | 20 min | 15 min |
| Understand | Draw or write the runtime flow in your own words | 20 min | 15 min |
| Code | Build the smallest working example in your project repo | 45 min | 35 min |
| Debug or Think | Force a failure, or answer one "what if" question | 25 min | 15 min |
| Review | Explain out loud for two minutes; write the journal entry; add flashcards | 10 min | 10 min |
Weekly rhythm
| Day | Focus |
|---|---|
| D1 and D2 | New concept: learn, understand, small experiments |
| D3 and D4 | Build the concept into the current project |
| D5 | Break it: failure injection, debugging, performance check |
| D6 | Integrate and interview: finish the project task, answer the week's questions aloud |
| D7 (review) | Journal re-read, flashcards, cleanup, plan the next week |
Task format ProgVale can generate
Each day is one record, so the roadmap can be generated into a calendar, a tracker or a daily email.
day: 61
week: 11
phase: 5
level: 2
topic: How @Transactional works
prerequisites: [spring-aop-proxies, jdbc-connection-pools]
learn: Spring docs on declarative transactions
understand: Draw proxy -> interceptor -> transaction manager -> connection
code: Two writes in one transactional service method
debug: Fail the second write; compare unchecked vs checked exceptions
think: What happens on a self-invoked call?
interview: Explain commit and rollback step by step
review: [journal entry, 2 flashcards]
minutes: 120
project_link: project-2
Three sample days
Day 61 (week 11, day 1): How @Transactional works
- Learn: the declarative transaction section of the Spring reference docs.
- Understand: the proxy intercepts the call,
TransactionInterceptorasks the transaction manager for a connection, the connection is bound to the thread, then commit or rollback. By default only unchecked exceptions roll back. - Code: a service method that creates an order and an audit row inside one transaction.
- Debug: throw a
RuntimeExceptionafter the second write and confirm both roll back; throw a checked exception and observe the commit. Turn on transaction trace logging. - Think: what happens if another method in the same class calls it? What if the method is
private? - Interview: explain the full sequence from controller call to commit.
- Review: one journal entry, two flashcards.
Day 88 (week 15, day 4): Cache stampede
- Learn: what a stampede is and the usual defenses: per-key locking, request coalescing, TTL jitter, early refresh.
- Understand: why one expired hot key can become hundreds of identical database queries.
- Code: a cache-aside endpoint, then a script firing 200 concurrent requests at an expired key while you count database hits.
- Debug: add a per-key lock; measure the database hits again. Record both numbers.
- Think: what if the lock holder crashes? What if the database is slow, so waiting requests pile up?
- Interview: "A hot key expires at peak traffic. What happens and how do you prevent it?"
- Review: journal entry with the before and after numbers.
Day 117 (week 20, day 3): Correlation IDs
- Learn: MDC in Logback and how a request ID is passed in an HTTP header and a Kafka header.
- Understand: MDC is thread-local, so the ID disappears when work moves to another thread.
- Code: a filter that accepts or generates
X-Request-Id, puts it in MDC, and forwards it on outgoingRestClientcalls and Kafka messages. - Debug: run an
@Asyncmethod and watch the ID go missing; fix it with a task decorator that copies the context. - Think: what if the client sends a malicious or very long ID? How do you search for one request across three services?
- Interview: "How do you trace one request across services?"
- Review: journal entry and flashcards.
Converting the roadmap into days
- Take each row of the week tables in section B; its "Practical task" becomes the Code step and its "Why it matters" becomes the Understand step.
- Add a Debug or Think step from the phase's production scenarios.
- Attach the phase's interview questions to the matching days.
- Link each day to the project it extends, and to the standalone article in section H when one exists.
- Add the review day with the journal re-read and the week's flashcards.
H. Article and content structure
This roadmap should be the pillar page. Each topic below earns a standalone article because it answers a question working developers actually search for. Forty articles cover the roadmap; start with the nine marked first, which are the strongest differentiators from generic roadmap sites.
Types: Explainer (how it works), Debugging (symptom to cause), Design (trade-offs and architecture).
| Article | Week | Type | Priority |
|---|---|---|---|
| How Java HashMap works internally, and why mutable keys break it | 1 | Explainer | |
| equals and hashCode: the contract and the bugs it causes | 1 | Explainer | |
| JVM memory for backend developers: heap, stack, metaspace | 2 | Explainer | |
| Garbage collection in practice: reading GC logs | 2 | Debugging | |
| Spring bean lifecycle: from startup to ready | 3 | Explainer | |
| How Spring Boot auto-configuration really works | 3 | Explainer | |
| Spring AOP proxies and the self-invocation trap | 4 | Explainer | first |
| The journey of an HTTP request through Spring MVC | 4 | Explainer | |
| Global exception handling with Problem Details | 5 | Explainer | |
| Idempotent POST APIs with idempotency keys | 6 | Design | |
| Offset vs cursor pagination | 6 | Design | |
| Connection pool exhaustion: causes and diagnosis | 7 | Debugging | first |
| How database indexes work: B-trees and composite indexes | 8 | Explainer | |
| Reading EXPLAIN ANALYZE output | 8 | Debugging | first |
| Isolation levels shown with real anomalies | 8 | Explainer | |
| The JPA N+1 problem: detect and fix | 10 | Debugging | first |
| Spring transaction internals | 11 | Explainer | first |
| Transaction propagation explained with failing examples | 11 | Explainer | |
| Optimistic vs pessimistic locking for inventory | 11 | Design | |
| What not to mock: integration tests with Testcontainers | 12 | Explainer | |
| JWT done right: validation, refresh and revocation | 13 | Explainer | |
| Preventing IDOR in Spring Boot APIs | 13 | Debugging | |
| Graceful shutdown and zero-downtime deployments | 14 | Explainer | |
| Redis cache-aside in Spring Boot | 15 | Explainer | first |
| Cache stampede, hot keys and cache penetration | 15 | Debugging | |
| ThreadPoolExecutor internals and pool sizing | 16 | Explainer | |
| Java virtual threads: what changes in Spring Boot | 17 | Explainer | first |
| Reading a thread dump to find a deadlock | 17 | Debugging | |
| Kafka consumer groups, partitions and offsets | 18 | Explainer | first |
| Kafka delivery semantics and idempotent consumers | 19 | Design | |
| Dead-letter topics and retry design with Spring Kafka | 19 | Design | |
| The transactional outbox pattern in Spring Boot | 19 | Design | |
| Debugging a slow checkout: metrics, traces and logs | 20 | Debugging | first |
| Correlation IDs across HTTP, threads and Kafka | 20 | Explainer | |
| High CPU and memory leaks in a Spring Boot service | 21 | Debugging | |
| Diagnosing Kafka consumer lag | 21 | Debugging | |
| Timeouts, retries and circuit breakers with Resilience4j | 22 | Design | |
| Saga pattern vs distributed transactions | 22 | Design | |
| Monolith vs modular monolith vs microservices: a decision guide | 22 | Design | |
| System design series: URL shortener, rate limiter, notification system | 23 | Design |
Article template
Use the same skeleton so the articles feel like one series and can be generated or reviewed consistently.
- A real problem: a short production symptom the reader recognizes.
- Mental model: one diagram of the runtime flow.
- How it works: the internals, with the smallest code that shows it.
- How it breaks: a failure you can reproduce.
- How to debug it: the tools and the order of checks.
- Production checklist: five or six concrete rules.
- Interview questions: concept, scenario and debugging versions, with a short model answer.
- Next steps: links to the previous topic and the next one on the roadmap.
Content clusters
| Cluster | Articles | Purpose |
|---|---|---|
| Spring internals | Proxies, bean lifecycle, auto-configuration, request flow, transactions | Rank for "how does X work in Spring" |
| Database and JPA | Indexes, EXPLAIN, N+1, pools, isolation, locking | Rank for the most common production problems |
| Production debugging | Slow checkout, CPU, memory, lag, pool exhaustion, thread dump | The strongest differentiator: symptom-first articles |
| Messaging | Consumer groups, semantics, DLQ, outbox | Practical Kafka for Spring developers |
| Interview prep | A question bank per level, built from section B | Converts readers into learners |
Cross-link every article to its roadmap phase, and the roadmap back to every article.
I. Missing topics
Reviewing the roadmap as a hiring engineer, the largest gap is data structures and algorithms, which SDE-1 and SDE-2 interviews still test. The other gaps are small but real: build tools, networking, low-level design practice, and a few operational topics. They add about 25 hours, taken from the weekly review days (which have slack) rather than extending the 26 weeks.
The biggest gap: data structures and algorithms
This roadmap builds engineering ability, not coding-round speed. Plan separate time of 4 to 5 hours per week alongside the roadmap, so it is outside the 310 hours. A workable scope for backend roles: arrays and strings, hashing, two pointers and sliding window, stacks and queues, linked lists, trees and BSTs, heaps, graphs (BFS and DFS), recursion and basic dynamic programming. About 120 well-chosen problems are enough for most SDE-1 loops; SDE-2 adds more medium problems and clear explanation of complexity. Start from week 1 and keep going through week 26.
Additions, and where they fit
| Missing topic | Why it matters | Where it fits |
|---|---|---|
| Maven or Gradle, BOMs, dependency conflicts, IDE debugger and remote debugging | Daily work; dependency conflicts cause real startup failures | Week 3, day 1 (90 minutes) |
| Networking basics: TCP, HTTP/1.1 vs HTTP/2, TLS, DNS, keep-alive, load balancer behavior | Explains timeouts, resets and slow connections | Weeks 6 and 14 (two 90-minute slots) |
Linux troubleshooting: top, ss, lsof, curl, file descriptors, container memory limits |
Needed in every production investigation | Week 21 review day |
| SOLID and low-level design problems (parking lot, rate limiter classes, elevator) | Most SDE-1 and SDE-2 loops have an LLD round | One problem every second review day, weeks 12 to 24 |
| Cloud literacy: managed database, object storage, queues, IAM, load balancer | Most teams deploy to a cloud; know the vocabulary and the managed equivalents | Week 14 review day |
| Backups, failover, RPO and RTO | A design is incomplete without recovery | Week 22 review day, then used in system design |
| NoSQL trade-offs: document stores, wide-column, when not to use a relational database | Required in design interviews | Week 23 day 1 |
| gRPC, GraphQL and WebFlux awareness | Often mentioned; you should know what they are and why REST plus virtual threads is usually enough | Week 22 review day (one hour each, reading only) |
| File upload, object storage and pre-signed URLs | Common in real APIs | Week 6 review day |
| Writing: design notes, decision records, incident postmortems | An SDE-2 communicates decisions and learns from incidents | Weeks 14, 22 and 26; convert the best journal entries into postmortems |
Deliberately left out
- Kubernetes administration: only concepts you need as a service developer (week 14).
- Reactive programming with WebFlux: awareness only. With virtual threads, most Spring services no longer need the reactive model for scalability.
- Spring Cloud suite: service discovery, config servers and gateways are mentioned, not taught; the resilience and messaging fundamentals transfer to any tool.
- Kafka Streams, advanced Spring Batch, GraphQL: valuable later, not needed for the SDE-2 target.
- Frontend, mobile and machine learning: outside the scope of a backend roadmap.
A version caveat
Build on a current Spring Boot release with Java 21 or later. Concepts here are stable across Spring Boot 3.x and later versions, but property names, defaults and supported Hibernate or Kafka versions change, so check the current official documentation for the version you install. Anything labeled "Java 21" or "Boot 3.2+" (such as the virtual-thread property) should be re-verified in week 17.
The honest summary
The roadmap covers the engineering path you described: request, controller, service, repository, database, cache, Kafka, external services, threads, JVM, logs, metrics, failures and scaling. It is demanding but finishable at 1.5 to 2.5 hours a day. If time runs short, protect these four phases above all others: JPA and transactions (5), concurrency (10), observability (12) and Kafka (11). They are where SDE-2 candidates most often fall short.
Notes & links
Saved automatically.