Complete Path · 4–5 hrs/day · 31 Topics · Interview-Ready

Java Backend
Complete Roadmap

Every important topic, in exact order, with official docs + videos + practice links. You know Java basics and Node.js — this starts from your gaps and builds to production-grade skills. Skip topics you know using the ⚡ button.

⚡ 3–4 months intensive
📦 31 topics, 100+ subtopics
🎯 Interview tags on every topic
✓ Progress saved in browser
🏗 Build projects per phase
Phase 1 — Fill Java Gaps
Week 1–2 · ~40 hrs
01
Java Core
OOP — The Deep Parts
⏱ 4 days · Spring relies on every one of these
You know classes, objects, inheritance. This phase fills the gaps Spring actually uses — abstract classes, interfaces, generics, exceptions. Don't skip if you haven't written production Java.
⚡ Know this already — mark all done
Abstract Classes vs Interfaces — When to Use Each
Must Know
Core Concepts
  • Abstract class — can have state (fields), constructors, concrete + abstract methods. Use when: IS-A with shared behavior/state
  • Interface — contract only (pre-Java 8). Use when: CAN-DO capability across unrelated classes
  • Default methods in interfaces (Java 8+) — interfaces can now have concrete methods: default void log() { ... }
  • Static methods in interfaces — utility methods: static int compare(A a, B b)
  • Multiple interface implementation — a class can implement many interfaces but extend only one class
  • Marker interfaces — empty interfaces for tagging: Serializable, Cloneable, Remote
  • Functional interface — exactly ONE abstract method. Enables lambda assignment. @FunctionalInterface enforces this INTERVIEW
Sub-topics
  • Sealed interfaces (Java 17) — restrict which classes can implement
  • Interface segregation principle (ISP) — keep interfaces small and focused
  • Why Spring beans implement interfaces — for JDK dynamic proxy (AOP)
🎯 Interview

"Why does Spring recommend coding to interfaces?" — Spring creates proxies (for @Transactional, @Cacheable) using JDK Proxy which requires an interface, or CGLIB which subclasses. Interface makes your code mockable in tests too.

Generics — <T>, Wildcards, Type Erasure
Important
  • Generic classes: class Repository<T> — type parameter makes class reusable
  • Generic methods: <T extends Comparable<T>> T max(T a, T b)
  • Upper bounded wildcard: List<? extends Number> — read-only, accepts Number and subclasses
  • Lower bounded wildcard: List<? super Integer> — write-friendly, accepts Integer and parents
  • Unbounded wildcard: List<?> — unknown type, very flexible
  • Type erasure — generics are compile-time only. At runtime List<String> becomes List. Cannot do new T() at runtime INTERVIEW
  • PECS rule: Producer Extends, Consumer Super — when in doubt what wildcard to use
Exception Handling — Checked, Unchecked, Custom
Must Know
  • Exception hierarchy: Throwable → Error (JVM errors) | Exception → RuntimeException (unchecked) INTERVIEW
  • Checked exceptions — must declare with throws or catch. E.g. IOException, SQLException
  • Unchecked exceptions — RuntimeException subclasses. No forced handling. Spring uses these exclusively
  • try-catch-finally — finally always runs (even if exception thrown)
  • try-with-resources — auto-closes Closeable: try (Connection c = ds.getConnection()) { ... }
  • Multi-catch: catch (IOException | SQLException e)
  • Custom exception: extend RuntimeException, add message + cause constructor
  • Exception chaining: throw new ServiceException("msg", originalException) — preserve root cause
🎯 Interview

"Why does Spring use unchecked exceptions?" — Forces callers to handle every possible exception (checked) breaks API contracts when internal implementation changes. Unchecked lets global @ControllerAdvice catch everything at the boundary.

Collections Framework — List, Map, Set, Queue
Must Know
  • List: ArrayList (O(1) get, O(n) insert), LinkedList (O(1) insert, O(n) get), Vector (synchronized legacy)
  • Map: HashMap (unordered, O(1) avg), LinkedHashMap (insertion order), TreeMap (sorted keys, O(log n)), ConcurrentHashMap (thread-safe) INTERVIEW
  • Set: HashSet (no duplicates, backed by HashMap), LinkedHashSet (ordered), TreeSet (sorted)
  • Queue/Deque: LinkedList, ArrayDeque, PriorityQueue
  • Immutable collections: List.of(), Map.of(), Set.of() (Java 9+)
  • Collections utility class: sort(), shuffle(), unmodifiableList(), synchronizedList()
  • Comparable vs Comparator — natural ordering vs custom ordering INTERVIEW
  • equals() and hashCode() contract — if a.equals(b) then a.hashCode() == b.hashCode(). MUST override both INTERVIEW
🎯 Interview

"How does HashMap work internally?" — Array of buckets + LinkedList/TreeMap per bucket. hashCode() finds bucket, equals() finds exact key. Load factor 0.75 triggers resize. Java 8+: bucket becomes TreeMap when size > 8 (O(log n) worst case).

02
Java Core
Functional Java — Lambdas, Streams, Optional
⏱ 4 days · Critical — all modern Java backend code uses these
This is the most important gap to fill. Spring code, Spring Data, Spring Security — all use lambdas and streams heavily. If you can't read them fluently, you'll struggle to use Spring effectively.
⚡ Know this already — mark all done
Lambda Expressions & Functional Interfaces
Critical
  • Syntax: (a, b) -> a + b or (a, b) -> { return a + b; }
  • Built-in functional interfaces: Predicate<T> (boolean test), Function<T,R> (R apply), Consumer<T> (void accept), Supplier<T> (T get), BiFunction, BiConsumer, BiPredicate
  • Method references 4 types: String::toUpperCase (instance), Math::max (static), list::add (bound), String::new (constructor)
  • Function composition: f.andThen(g) — f then g; f.compose(g) — g then f
  • Predicate composition: p1.and(p2), p1.or(p2), p1.negate()
  • Effectively final — variables used in lambdas must be final or effectively final INTERVIEW
Streams API — Complete Guide
Critical
Creating Streams
  • list.stream(), Arrays.stream(arr), Stream.of(a,b,c), Stream.generate(), Stream.iterate(), IntStream.range(0,10)
Intermediate (lazy, return Stream)
  • filter(Predicate), map(Function), flatMap(Function), distinct(), sorted(), sorted(Comparator), limit(n), skip(n), peek(Consumer) (debug only)
Terminal (eager, consume Stream)
  • collect(), forEach(), reduce(identity, BinaryOperator), count(), findFirst(), findAny(), anyMatch(), allMatch(), noneMatch(), min(), max(), toArray()
Collectors (most important)
  • Collectors.toList(), toSet(), toMap(key, val), joining(", ")
  • groupingBy(classifier) — returns Map<K, List<T>>
  • groupingBy(classifier, counting()) — returns Map<K, Long>
  • partitioningBy(Predicate) — returns Map<Boolean, List<T>>
  • collectingAndThen(toList(), Collections::unmodifiableList)
  • Collectors.toUnmodifiableList() (Java 10+)
  • map vs flatMap: map is 1-to-1, flatMap is 1-to-many and flattens nested streams INTERVIEW
  • Parallel streams: list.parallelStream() — uses ForkJoinPool. Only faster if work per element is heavy AND order doesn't matter INTERVIEW
  • Streams are not reusable — once terminal op called, stream is closed
Optional — Null-Safe Programming
Important
  • Creating: Optional.of(value) (NPE if null), Optional.ofNullable(value) (safe), Optional.empty()
  • Checking: isPresent(), isEmpty() (Java 11)
  • Getting: get() (throws if empty), orElse(default), orElseGet(() -> compute()), orElseThrow(), orElseThrow(ExceptionSupplier)
  • Transforming: map(Function), flatMap(Function), filter(Predicate)
  • Side effects: ifPresent(Consumer), ifPresentOrElse(Consumer, Runnable) (Java 9)
  • Don't use Optional as: method parameter, field, or collection element INTERVIEW
  • Spring Data JPA returns Optional<T> from findById() — chain .orElseThrow(() -> new NotFoundException(...))
03
Java Core
Concurrency & Multithreading
⏱ 3 days · Interview heavy — understand conceptually
Spring handles threading for you in web apps, but concurrency questions are frequent in interviews. You need to understand threads, locks, and async execution to read Spring internals too.
⚡ Know this already — mark all done
Threads, Runnable, Callable, Future
Interview Heavy
  • Thread lifecycle: NEW → RUNNABLE → BLOCKED/WAITING/TIMED_WAITING → TERMINATED INTERVIEW
  • Runnable — no return value: new Thread(() -> doWork()).start()
  • Callable<T> — returns value + throws checked exceptions
  • Future<T> — handle for async result: future.get() (blocks), future.isDone()
  • Race condition — two threads access shared mutable state without synchronization INTERVIEW
  • Deadlock — thread A holds lock X waits for Y, thread B holds Y waits for X INTERVIEW
  • synchronized keyword — only one thread at a time enters block. Works on object monitor
  • volatile — guarantees visibility (changes visible to all threads), not atomicity INTERVIEW
  • AtomicInteger, AtomicLong, AtomicReference — lock-free thread-safe operations
ExecutorService, Thread Pools, CompletableFuture
Must Know
  • ExecutorService — manages a pool of threads: Executors.newFixedThreadPool(10), newCachedThreadPool(), newSingleThreadExecutor()
  • submit() vs execute() — submit returns Future, execute is fire-and-forget
  • shutdown() vs shutdownNow() — graceful vs immediate
  • CompletableFuture — async pipelines without blocking
  • Creating: CompletableFuture.supplyAsync(() -> fetch()), runAsync(() -> doWork())
  • Chaining: thenApply(Function) (same thread), thenApplyAsync(Function) (new thread)
  • Completion: thenAccept(Consumer), thenRun(Runnable)
  • Combining: thenCompose() (flat-map), thenCombine() (combine two futures)
  • Error handling: exceptionally(ex -> fallback), handle(BiFunction)
  • Virtual Threads (Java 21) — lightweight threads managed by JVM, not OS. Spring Boot 3.2+ supports them. Fix for thread-per-request scalability INTERVIEW
04
Java Core
Modern Java — Records, Sealed Classes, Pattern Matching
⏱ 2 days · Modern code uses these everywhere
⚡ Know this already — mark all done
Records, Sealed Classes, Pattern Matching, Text Blocks
Modern Java
  • Records (Java 16) — immutable data carriers. record Point(int x, int y) {} auto-generates constructor, getters, equals, hashCode, toString. Use for DTOs INTERVIEW
  • Record limitations: no field mutation, can't extend classes, can't be JPA @Entity (needs no-arg constructor)
  • Compact constructors in records: validate in constructor body without repeating parameters
  • Sealed classes (Java 17): sealed class Shape permits Circle, Rectangle — restricts inheritance to listed classes
  • Pattern matching instanceof (Java 16): if (obj instanceof String s) { s.length(); } — no cast needed
  • Switch expressions (Java 14): String result = switch(day) { case MON -> "Mon"; default -> "Other"; }
  • Text blocks (Java 15): multiline strings with """...""" — great for JSON in tests
  • var (Java 10): local variable type inference — var list = new ArrayList<String>()
Phase 2 — Build Tools
Week 2 · ~8 hrs
05
Tooling
Maven — Dependency & Build Management
⏱ 2 days · Think of it as package.json + npm scripts for Java
⚡ Know this already — mark all done
pom.xml, Dependencies, Lifecycle, Plugins
Must Know
  • pom.xml coordinates: groupId (com.company), artifactId (project-name), version (1.0.0)
  • Parent POM: spring-boot-starter-parent manages all dependency versions — no version conflicts
  • Dependency scopes: compile (default, in classpath always), test (test only), provided (container provides it), runtime (not for compile)
  • Maven lifecycle phases: validate → compile → test → package → verify → install → deploy
  • Key commands: mvn clean package, mvn spring-boot:run, mvn test, mvn dependency:tree
  • Transitive dependencies — if A depends on B which depends on C, A gets C too. Can cause conflicts
  • Dependency exclusions — exclude a transitive dep you don't want
  • Profiles: <profiles> — different configs for dev/prod: mvn package -Pprod
  • Spring Boot Maven Plugin: creates executable fat JAR with embedded Tomcat
Phase 3 — Databases
Week 3–4 · ~40 hrs
06
Database
SQL Deep Dive — Queries, JOINs, Window Functions
⏱ 4 days · Learn SQL first — don't go to JPA without this
⚡ Know this already — mark all done
Core SQL — SELECT, JOINs, Aggregates, Subqueries, CTEs
Must Know
  • JOINs: INNER (matched both), LEFT (all left + matched right), RIGHT, FULL OUTER, CROSS, SELF JOIN
  • Aggregates: COUNT(*), COUNT(DISTINCT col), SUM, AVG, MAX, MIN — with GROUP BY and HAVING
  • Subqueries: in WHERE (correlated), in FROM (derived table), in SELECT (scalar)
  • CTEs (WITH clause): readable alternative to subqueries, can be recursive
  • Window functions: ROW_NUMBER(), RANK(), DENSE_RANK(), NTILE(), LAG(), LEAD(), FIRST_VALUE(), SUM() OVER() INTERVIEW
  • PARTITION BY: divide rows into groups for window functions
  • OVER(): defines the window: ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC)
  • LIMIT + OFFSET: LIMIT 10 OFFSET 20 — page 3 of size 10
  • DISTINCT, ORDER BY, NULLS FIRST/LAST
  • String functions: LOWER(), UPPER(), TRIM(), CONCAT(), SUBSTRING(), LIKE, ILIKE (postgres case-insensitive)
  • Date functions: NOW(), CURRENT_DATE, EXTRACT, DATE_TRUNC, AGE()
  • CASE WHEN: inline conditional logic in SELECT
  • COALESCE(a, b, c): first non-null value
07
Database
Database Design, Normalization & Indexing
⏱ 3 days
⚡ Know this already — mark all done
Relationships, Normalization, Keys
Must Know
  • Relationships: One-to-One, One-to-Many (most common), Many-to-Many (via junction table)
  • Primary key: uniquely identifies a row. Integer SERIAL/BIGSERIAL or UUID
  • Foreign key: references PK of another table. ON DELETE CASCADE vs RESTRICT vs SET NULL
  • Composite keys: multiple columns together form the PK (e.g. user_id + role_id in user_roles)
  • Normalization: 1NF (atomic values, no repeating groups) → 2NF (no partial dependency on composite key) → 3NF (no transitive dependency) INTERVIEW
  • Denormalization: intentionally duplicate data for read performance (e.g. reporting tables)
  • UUID vs auto-increment: UUID = globally unique, good for distributed systems; auto-increment = sequential, smaller, faster for indexing
PostgreSQL — Indexes, EXPLAIN, JSONB, Constraints
Important
  • B-tree index (default): best for equality and range queries. CREATE INDEX idx_email ON users(email)
  • When to add index: columns in WHERE, JOIN ON, ORDER BY, high cardinality (many unique values)
  • Composite indexes: CREATE INDEX ON orders(user_id, created_at) — order matters (leftmost prefix rule)
  • Partial index: CREATE INDEX ON users(email) WHERE active = true
  • EXPLAIN ANALYZE: shows query plan + actual execution time. Look for Seq Scan (bad on large tables) vs Index Scan (good)
  • Constraints: NOT NULL, UNIQUE, CHECK, FOREIGN KEY
  • JSONB: PostgreSQL's binary JSON column type. Can index into it with GIN index
  • Partial vs full table scan: understand when Postgres chooses index vs sequential scan
08
Database
Transactions, ACID, Locking & Connection Pooling
⏱ 2 days · Interview staple
ACID, Isolation Levels, Locking, Deadlocks
Interview Heavy
  • Atomicity — all operations in transaction succeed, or all fail (rolled back)
  • Consistency — transaction brings DB from one valid state to another (constraints must hold)
  • Isolation — concurrent transactions don't see each other's intermediate state
  • Durability — committed data persists even after crash (written to WAL/disk)
  • Isolation levels: READ UNCOMMITTED (dirty reads) → READ COMMITTED (default PostgreSQL) → REPEATABLE READ → SERIALIZABLE INTERVIEW
  • Read phenomena: Dirty read (uncommitted data), Non-repeatable read (data changed between reads), Phantom read (new rows appear between reads)
  • Optimistic locking: no lock, use @Version field, fail if stale. Good for low contention INTERVIEW
  • Pessimistic locking: SELECT FOR UPDATE — acquires row lock. Good for high contention
  • Deadlock: A waits for B's lock, B waits for A's. PostgreSQL detects and aborts one
  • HikariCP (Spring default): connection pool — reuse DB connections. Config: maximumPoolSize, minimumIdle, connectionTimeout
🎯 Interview

"Explain ACID" and "What's the difference between optimistic and pessimistic locking?" — Answer optimistic: use @Version annotation in JPA, @Lock(LockModeType.OPTIMISTIC). Pessimistic: @Lock(LockModeType.PESSIMISTIC_WRITE).

Phase 4 — Spring Boot (The Core)
Week 4–9 · Biggest Phase · ~120 hrs
09
Spring Core
IoC Container & Dependency Injection
⏱ 3 days · THE foundation. Understand this deeply.
If you understand IoC and DI at a deep level, every single Spring feature immediately makes sense. Spring Security, Spring Data, Spring Batch — all are just beans wired together.
IoC, DI, ApplicationContext, Bean Lifecycle
Critical
  • IoC (Inversion of Control) — you don't create objects, you describe what you need and Spring creates/wires them INTERVIEW
  • DI types: Constructor injection ✅ (immutable, testable, recommended), Setter injection, Field injection (@Autowired on field — avoid in new code)
  • @Component, @Service, @Repository, @Controller, @RestController — stereotype annotations, component-scan picks them up
  • @Bean + @Configuration — explicit bean creation for third-party classes you can't annotate
  • @Autowired — inject by type. With constructor injection, @Autowired is optional (implicit when one constructor)
  • @Qualifier("beanName") — disambiguate when multiple beans of same type
  • @Primary — mark one bean as default when multiple of same type
  • Bean scopes: Singleton (one per ApplicationContext, default), Prototype (new on each injection), Request (per HTTP request), Session (per HTTP session) INTERVIEW
  • Bean lifecycle: instantiate → inject dependencies → @PostConstruct → in use → @PreDestroy → destroyed
  • @PostConstruct / @PreDestroy — lifecycle callbacks
  • ApplicationContext vs BeanFactory — ApplicationContext extends BeanFactory, adds i18n, events, AOP, etc. Always use ApplicationContext
  • ApplicationEvent + @EventListener — loose coupling via events within the app
  • @Lazy — don't create bean until first use (saves startup time)
  • @ConditionalOnProperty, @ConditionalOnClass — create beans conditionally
🎯 Interview

"Explain Spring Bean lifecycle" — Instantiated via constructor → Dependencies injected → @PostConstruct called → ready → @PreDestroy called → destroyed. Also: "What's the difference between Singleton and Prototype scope?" Singleton = shared state risk, Prototype = new instance each time.

10
Spring Boot
Spring Boot — Auto-configuration, Profiles, Config
⏱ 2 days
Auto-configuration, Starters, application.yml, Profiles
Critical
  • @SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan on current package
  • Auto-configuration magic: add spring-boot-starter-web → Tomcat, Jackson, Spring MVC auto-configured. Reads META-INF/spring/auto-configuration files INTERVIEW
  • Starters: spring-boot-starter-web, data-jpa, security, test, validation, actuator, mail, cache, data-redis
  • application.yml (prefer over .properties): server.port, spring.datasource.url, spring.jpa.show-sql
  • @Value("${app.name:default}") — inject single property with default
  • @ConfigurationProperties(prefix="app") — bind group of properties to a typed class. Better than @Value for groups
  • Profiles: application-dev.yml, application-prod.yml. Activate with spring.profiles.active=dev or env var SPRING_PROFILES_ACTIVE=prod
  • @Profile("dev") — only create bean in this profile
  • Environment variables — override any property: SPRING_DATASOURCE_URL=... (dots become underscores, uppercase)
  • spring.factories / spring.auto-configuration.imports — how auto-config is discovered
11
Spring Boot
Spring MVC — REST Controllers & HTTP Layer
⏱ 4 days · Like Express.js but more structured
Controllers, Mappings, Request/Response, DispatcherServlet
Must Know
  • @RestController = @Controller + @ResponseBody — every method returns data, not view
  • @RequestMapping("/api/v1/users") — base path on class
  • Method annotations: @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
  • @PathVariable Long id — extract from URL path /users/{id}
  • @RequestParam(defaultValue="0") int page — query parameter /users?page=0&size=10
  • @RequestBody UserRequest req — deserializes JSON body via Jackson
  • @RequestHeader("Authorization") String token — extract header
  • ResponseEntity<T> — full control: body + status + headers: ResponseEntity.created(uri).body(dto)
  • DispatcherServlet — front controller pattern. All requests hit it, routed to handlers, response assembled INTERVIEW
  • Jackson — JSON serialization library. @JsonIgnore, @JsonProperty("name"), @JsonFormat
  • Content negotiation: produces/consumes on @RequestMapping — Accept and Content-Type headers
  • @CrossOrigin — enable CORS on specific endpoints (or configure globally)
12
Spring Boot
Spring Data JPA — Complete ORM Layer
⏱ 6 days · Most complex Spring topic. Take your time.
JPA is where most developers get stuck. The N+1 problem alone has caused production outages at major companies. Learn it properly, not just the happy path.
@Entity Mapping — Full Reference
Critical
  • @Entity + @Table(name="users") — maps class to DB table
  • @Id + @GeneratedValue: IDENTITY (DB auto-increment), SEQUENCE (DB sequence), UUID (@UuidGenerator)
  • @Column(name="email_address", unique=true, nullable=false, length=255)
  • @Transient — field not persisted to DB
  • @Enumerated(EnumType.STRING) — store enum as string (not ordinal!)
  • Auditing: @CreatedDate, @LastModifiedDate, @CreatedBy — extend AbstractAuditingEntity or use @EnableJpaAuditing
  • @Embedded + @Embeddable — embed value objects (Address, Money) into entity
  • @Version — optimistic locking: auto-incremented int on each update, throws OptimisticLockException on conflict
JpaRepository — CRUD, Derived Queries, @Query, Pagination
Critical
  • JpaRepository<Entity, ID>: save(), saveAll(), findById(), findAll(), delete(), existsById(), count()
  • Derived queries: Spring generates SQL from method name: findByEmailIgnoreCase(), findByAgeGreaterThan(), findByStatusIn(List)
  • findBy + And/Or/Between/Like/LessThan/GreaterThan/OrderBy
  • @Query JPQL: @Query("SELECT u FROM User u WHERE u.email = :email") — uses entity/field names
  • @Query nativeQuery=true: raw SQL — use when JPQL can't express the query
  • @Modifying + @Query: for UPDATE/DELETE queries. Requires @Transactional
  • Pagination: Page<User> findAll(Pageable pageable), pass PageRequest.of(page, size, Sort.by("name"))
  • Slice<T> — like Page but no total count query (faster for infinite scroll)
  • Custom Repository: interface MyCustomRepo + MyCustomRepoImpl class for complex queries
  • Specifications: type-safe dynamic WHERE clauses — use when filters are optional
JPA Relationships — N+1, Lazy vs Eager, Cascade, @EntityGraph
Critical + Interview
  • @OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true) — on parent side
  • @ManyToOne(fetch=FetchType.LAZY) — on child side, always make LAZY
  • @ManyToMany @JoinTable — creates junction table
  • Default fetch types: @OneToMany = LAZY, @ManyToOne = EAGER, @OneToOne = EAGER. Change EAGER to LAZY everywhere! INTERVIEW
  • N+1 Problem: findAll() loads 100 users (1 query) then accesses user.getOrders() on each (100 queries) = 101 queries INTERVIEW
  • Fix N+1: @Query("SELECT u FROM User u JOIN FETCH u.orders") or @EntityGraph(attributePaths={"orders"})
  • CascadeType: PERSIST (save child with parent), MERGE, REMOVE (delete child with parent), REFRESH, ALL
  • orphanRemoval=true — delete child when removed from parent's collection
  • @BatchSize(size=50) — batch load lazy collections to reduce queries
  • spring.jpa.show-sql=true — see what queries JPA generates (essential for debugging)
🎯 Interview

"What is the N+1 problem and how do you fix it?" — Critical question. Also be ready for "What's the difference between LAZY and EAGER loading?" and "When would you use @EntityGraph?"

Flyway — Database Migrations
Must Know
  • Why migrations: schema changes tracked in version control alongside code. Team members get same DB state
  • Naming: V1__create_users.sql, V2__add_email_index.sql, V3__create_orders.sql
  • Location: src/main/resources/db/migration/
  • Spring Boot auto-runs pending migrations at startup
  • Golden rule: never edit an already-applied migration. Create a new one instead
  • Baseline: for existing databases, create V1 as baseline
  • Repeatable migrations: R__seed_data.sql — re-runs when checksum changes
  • Undo scripts (paid feature): V2__undo.sql
  • Flyway tracks history in flyway_schema_history table
13
Spring Boot
Validation & DTOs — Clean API Layer
⏱ 2 days
DTOs with Records, Bean Validation, MapStruct
Must Know
  • DTO pattern: separate API shape from @Entity — avoids exposing DB structure, allows different shapes per endpoint INTERVIEW
  • Record DTOs: public record UserResponse(Long id, String email, String name) {} — immutable, auto equals/hashCode
  • Request vs Response DTO: UserCreateRequest (what comes in), UserResponse (what goes out), UserUpdateRequest (partial update)
  • @NotNull, @NotBlank, @NotEmpty — null/empty checks
  • @Size(min=2, max=50) — string length
  • @Email — email format validation
  • @Pattern(regexp="...") — regex validation
  • @Min, @Max, @Positive, @PositiveOrZero — numeric validation
  • @Valid on @RequestBody parameter — triggers validation. Returns 400 with errors if invalid
  • @Validated (class-level) — enables group validation
  • Custom validator: implement ConstraintValidator<Annotation, Type>
  • MapStruct: annotation processor generates mapper at compile time — @Mapper(componentModel = "spring")
14
Spring Boot
Global Exception Handling — @ControllerAdvice
⏱ 1 day
@ControllerAdvice, ProblemDetail, Custom Exception Hierarchy
Must Know
  • @ControllerAdvice — one class catches exceptions from all controllers globally
  • @ExceptionHandler(UserNotFoundException.class) — maps exception type to HTTP response
  • ProblemDetail (RFC 9457, Spring 6) — standardized error response: type, title, status, detail, instance INTERVIEW
  • ResponseEntityExceptionHandler — extend this to handle Spring MVC built-in exceptions
  • Custom exception hierarchy:
    BaseException (RuntimeException) → NotFoundException (404), ConflictException (409), ForbiddenException (403)
  • MethodArgumentNotValidException — thrown when @Valid fails. Extract field errors from BindingResult
  • HttpMessageNotReadableException — invalid JSON in request body
15
Spring Boot
AOP & @Transactional — Cross-Cutting Concerns
⏱ 2 days
AOP — Aspects, Advice, Pointcuts
Important
  • AOP purpose: apply cross-cutting concerns (logging, security, transactions) without modifying business code
  • Aspect — class with advice: @Aspect @Component class LoggingAspect
  • Pointcut — expression defining where advice runs: @Pointcut("execution(* com.app.service.*.*(..))")
  • Advice types: @Before (before method), @After (after regardless), @AfterReturning (after success), @AfterThrowing (after exception), @Around (wrap method — most powerful)
  • JoinPoint — represents the method being intercepted. Access method name, args, return value
  • ProceedingJoinPoint — used in @Around: Object result = pjp.proceed()
  • Spring AOP uses JDK Proxy (interface-based) or CGLIB (class subclassing) INTERVIEW
  • Self-invocation problem: calling annotated method from same class bypasses proxy — AOP doesn't apply INTERVIEW
@Transactional — Full Reference
Critical + Interview
  • @Transactional — Spring wraps method in DB transaction. Commit on success, rollback on RuntimeException
  • Propagation.REQUIRED (default) — join existing transaction or create new one INTERVIEW
  • Propagation.REQUIRES_NEW — always new transaction, suspends outer
  • Propagation.SUPPORTS — run in transaction if one exists, else without
  • Propagation.NOT_SUPPORTED — suspend any existing transaction
  • rollbackFor=Exception.class — by default, ONLY rolls back on RuntimeException! Add this for checked exceptions INTERVIEW
  • noRollbackFor — don't rollback for this specific exception
  • readOnly=true — performance hint for SELECT-only methods (Hibernate optimizations)
  • timeout=30 — transaction timeout in seconds
  • Isolation level — set per transaction: @Transactional(isolation=Isolation.READ_COMMITTED)
  • Self-invocation problem — method A calls @Transactional method B in same class → B's @Transactional is ignored because proxy is bypassed INTERVIEW
🎯 Interview

"What happens when @Transactional method throws a checked exception?" — No rollback by default. This surprises many. Fix: @Transactional(rollbackFor = Exception.class). Also: "Explain the self-invocation problem with @Transactional."

16
Spring Boot
REST API Design Best Practices
⏱ 2 days
REST Principles, HTTP Semantics, Pagination, Idempotency
Must Know
  • Resource naming: nouns plural: /users, /orders, /products. Not /getUsers, not /createProduct
  • HTTP semantics: GET (read, safe, idempotent), POST (create, not idempotent), PUT (full replace, idempotent), PATCH (partial update), DELETE (idempotent) INTERVIEW
  • Status codes: 200 OK, 201 Created (+ Location header), 204 No Content (DELETE/PUT success), 400 Bad Request, 401 Unauthorized (not logged in), 403 Forbidden (logged in, no permission), 404 Not Found, 409 Conflict (duplicate), 422 Unprocessable Entity (validation), 429 Too Many Requests, 500 Internal Server Error INTERVIEW
  • Versioning: /api/v1/users — in URL path (most common), or Accept: application/vnd.app.v1+json header
  • Pagination response envelope: { "data": [...], "page": 0, "size": 10, "totalElements": 100, "totalPages": 10 }
  • Cursor-based pagination — better for large datasets, uses last-seen ID: ?after=abc123
  • Filtering + sorting: ?status=ACTIVE&sort=name,asc&sort=createdAt,desc
  • Idempotency key — Idempotency-Key header for POST requests to prevent duplicate operations
  • HATEOAS — include links in response to related resources (optional, used in REST Level 3)
17
Spring Boot
API Documentation — OpenAPI / Swagger + Actuator
⏱ 1 day
Springdoc OpenAPI, Swagger UI, Spring Actuator
Must Know
  • Springdoc OpenAPI — add dependency, get Swagger UI at /swagger-ui.html automatically
  • @Operation(summary="...", description="...") — document an endpoint
  • @Parameter(description="...", example="...") — document a parameter
  • @ApiResponse(responseCode="200", description="...")
  • @Schema(description="...", example="...") — document DTO fields
  • OpenAPI spec — generated at /v3/api-docs (JSON), use to generate client SDKs
  • Spring Boot Actuator — add spring-boot-starter-actuator, get: /actuator/health, /actuator/info, /actuator/metrics, /actuator/env INTERVIEW
  • Actuator: expose endpoints selectively in production (never expose /actuator/env publicly)
  • Custom health indicators — implement HealthIndicator for custom /health checks
🏗 Build — Phase 4 Checkpoint

Build a complete Blog API: Users, Posts (with tags), Comments. Use PostgreSQL + Flyway + DTOs with validation + global exception handler + pagination + OpenAPI docs. This project alone touches 90% of Spring Boot. Push to GitHub.

Phase 5 — Security
Week 9–11 · ~50 hrs
18
Security
Spring Security Core — Filter Chain, UserDetails, BCrypt
⏱ 5 days · Steepest learning curve in Spring
Understand the SecurityFilterChain FIRST. Every request passes through filters in order. Once you see the chain, JWT and OAuth2 become "just another filter."
SecurityFilterChain, Authentication, UserDetails, CSRF, CORS
Critical
  • SecurityFilterChain — ordered list of filters. Every HTTP request passes through all filters INTERVIEW
  • Key filters: UsernamePasswordAuthenticationFilter, BasicAuthenticationFilter, JwtAuthenticationFilter (custom)
  • SecurityContext / SecurityContextHolder — stores current user's Authentication. ThreadLocal by default
  • Authentication object — principal (UserDetails), credentials, authorities (roles)
  • AuthenticationManager — delegates to AuthenticationProvider chain to authenticate
  • UserDetails interface — getUsername(), getPassword(), getAuthorities(), isEnabled(), isAccountNonLocked()
  • UserDetailsServiceloadUserByUsername(String username) — load user from DB
  • PasswordEncoder — always BCryptPasswordEncoder. NEVER store plain text. NEVER MD5/SHA INTERVIEW
  • SecurityFilterChain @Bean config: .csrf().disable() for REST APIs, .sessionManagement(stateless), .authorizeHttpRequests()
  • CSRF — disable for stateless REST (no cookies/sessions). Keep enabled for form-based apps
  • CORS — configure allowed origins, methods, headers via CorsConfigurationSource bean
  • DaoAuthenticationProvider — wires UserDetailsService + PasswordEncoder together
Authorization — Roles, @PreAuthorize, Method Security
Must Know
  • @EnableMethodSecurity — MUST add to config class to enable method-level annotations INTERVIEW
  • @PreAuthorize("hasRole('ADMIN')") — check before method runs
  • @PostAuthorize("returnObject.owner == authentication.name") — check after method returns
  • Roles vs Authorities: roles are prefixed with ROLE_ internally. hasRole('ADMIN') = hasAuthority('ROLE_ADMIN') INTERVIEW
  • URL-level security in config: .requestMatchers("/admin/**").hasRole("ADMIN")
  • Method expressions: hasRole(), hasAnyRole(), hasAuthority(), isAuthenticated(), isAnonymous(), permitAll(), denyAll()
  • Get current user: @AuthenticationPrincipal UserDetails user in controller method parameter
  • SecurityContextHolder.getContext().getAuthentication() — get current auth anywhere
  • Custom AccessDeniedHandler — return clean 403 JSON response
  • Custom AuthenticationEntryPoint — return clean 401 JSON response
19
Security
JWT Authentication — Complete Implementation
⏱ 4 days
JWT — Structure, Flow, Filter, Refresh Tokens
Industry Standard
  • JWT structure: header.payload.signature (base64url-encoded) INTERVIEW
  • Header: algorithm (HS256, RS256) + token type
  • Payload claims: sub (subject/userId), iat (issued at), exp (expiry), custom: roles, email
  • Signature: HMAC-SHA256(base64(header).base64(payload), secret). Tamper-proof
  • Stateless auth flow: POST /auth/login → validate credentials → sign JWT → return access token + refresh token in response
  • Client sends: Authorization: Bearer <access_token> on every request
  • JwtAuthenticationFilter (extends OncePerRequestFilter): extract token → validate → build Authentication → set in SecurityContext
  • Access token — short-lived (15 min). Stateless. Can't be revoked without blacklist
  • Refresh token — long-lived (7–30 days). Stored in DB. Can be revoked. Used to get new access token INTERVIEW
  • Rotation strategy — issue new refresh token on each use, invalidate old one
  • Token storage: HttpOnly cookie (XSS-safe, CSRF risk) vs localStorage (CSRF-safe, XSS risk)
  • JWT libraries: io.jsonwebtoken:jjwt or Spring's built-in OAuth2 Resource Server (preferred)
  • RS256 vs HS256 — RS256 uses asymmetric keys (public key to verify, private to sign) — better for microservices
🎯 Interview

"How does JWT authentication work?" "What's access token vs refresh token?" "Can JWT be revoked?" (No, unless you maintain a blacklist or use short expiry + refresh tokens). These are standard questions.

20
Security
OAuth2, OpenID Connect, Social Login
⏱ 3 days
OAuth2 Authorization Code Flow, OIDC, Spring OAuth2 Client
Important
  • OAuth2 purpose — delegate authentication to trusted provider (Google, GitHub, Azure AD)
  • Authorization Code Flow: User → App → Auth Server (login page) → code → App exchanges code for token → App uses token for API calls INTERVIEW
  • PKCE (Proof Key for Code Exchange) — required for public clients (mobile, SPA). Prevents auth code interception
  • OpenID Connect (OIDC) — adds identity layer on top of OAuth2. Returns ID token (JWT) with user info (sub, email, name)
  • OAuth2 Client (Spring) — configure providers in application.yml: google, github, okta. Spring handles the flow
  • Roles: Resource Owner (user), Client (your app), Authorization Server (Google), Resource Server (API)
  • Keycloak — self-hosted Identity Provider. Good for enterprise: users, roles, realms, clients
  • Token types in OAuth2: Access Token (for API), ID Token (user identity), Refresh Token
Phase 6 — Testing
Week 11–12 · ~40 hrs
21
Testing
JUnit 5 & Mockito — Unit Testing
⏱ 3 days
JUnit 5 — Complete Testing Reference
Must Know
  • @Test — test method. @DisplayName("readable name")
  • @BeforeEach / @AfterEach — setup/teardown per test
  • @BeforeAll / @AfterAll — run once per class (must be static)
  • Assertions: assertEquals(expected, actual), assertNotNull(), assertTrue(), assertFalse(), assertThrows(Exception.class, () → ...), assertDoesNotThrow(), assertAll()
  • assertThrows: UserNotFoundException ex = assertThrows(UserNotFoundException.class, () -> service.findById(-1L)); assertEquals("User not found", ex.getMessage())
  • @ParameterizedTest + @ValueSource: @ValueSource(strings = {"", " ", "invalid@"})
  • @MethodSource("provideTestData") — static method returns Stream<Arguments>
  • @CsvSource({"1, one", "2, two"}) — tabular test data
  • @Nested — inner class for grouping related tests
  • @Disabled("reason") — skip test temporarily
  • @Tag("integration") — tag tests for selective running
  • AAA pattern: Arrange (setup) → Act (call) → Assert (verify) — structure every test INTERVIEW
  • Test naming: methodName_StateUnderTest_ExpectedBehavior — e.g. findById_WhenUserNotFound_ThrowsException
Mockito — Mocking, Stubbing, Verification
Must Know
  • @ExtendWith(MockitoExtension.class) — required on test class for JUnit 5
  • @Mock — create mock of dependency. @Spy — real object but can stub specific methods
  • @InjectMocks — create instance of class under test and inject @Mocks
  • when(mock.method(arg)).thenReturn(value) — stub method call
  • when(mock.method(any())).thenThrow(new RuntimeException()) — simulate failure
  • doReturn, doThrow, doAnswer — for void methods or Spy
  • verify(mock).method(arg) — assert method was called exactly once
  • verify(mock, times(2)).method() — called exactly N times
  • verify(mock, never()).method() — never called
  • ArgumentCaptor<T> — capture argument passed to mock: ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class); verify(repo).save(captor.capture()); assertEquals("John", captor.getValue().getName())
  • ArgumentMatchers: any(), anyString(), anyLong(), eq("exact"), argThat(predicate)
  • Mockito.mockStatic() — mock static methods (Mockito 3.4+)
22
Testing
Spring Boot Testing — @SpringBootTest, MockMvc, @WebMvcTest
⏱ 3 days
Slice Tests, MockMvc, @MockBean, Integration Tests
Must Know
  • @SpringBootTest — loads full ApplicationContext. Slow. Use for integration tests only
  • @SpringBootTest(webEnvironment=RANDOM_PORT) — starts real server on random port. Use with TestRestTemplate
  • @WebMvcTest(UserController.class) — loads only web layer (controllers, filters). Fast. Mock services with @MockBean
  • @DataJpaTest — loads only JPA layer. Uses in-memory H2. Good for repository tests
  • @MockBean — replace a Spring bean in context with Mockito mock. Different from @Mock (no Spring context)
  • MockMvc — test HTTP requests without a real server: mockMvc.perform(get("/users/1")).andExpect(status().isOk()).andExpect(jsonPath("$.email").value("[email protected]"))
  • @AutoConfigureMockMvc — auto-configure MockMvc in @SpringBootTest
  • TestRestTemplate — makes real HTTP calls in @SpringBootTest with RANDOM_PORT
  • WebTestClient — reactive alternative to TestRestTemplate, fluent API
  • @Sql — run SQL scripts before/after test: @Sql("/test-data.sql")
  • @Transactional on test class — rolls back all DB changes after each test
  • jsonPath assertions: $.fieldName, $.list[0].name, $.list.length()
23
Testing
Testcontainers & WireMock — Real Dependencies in Tests
⏱ 2 days
Testcontainers, WireMock, Test Coverage
Must Know
  • Testcontainers — spin up real Docker containers (PostgreSQL, Redis, Kafka) during tests. Tests against real infrastructure, not mocks INTERVIEW
  • @Testcontainers + @Container — JUnit 5 integration: @Container static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16")
  • @DynamicPropertySource — inject container connection URL into Spring context
  • Singleton containers — reuse container across tests for speed: static { container.start(); }
  • WireMock — mock external HTTP APIs your service calls. Stub with: stubFor(get("/api/users/1").willReturn(okJson(userJson)))
  • @WireMockTest — Spring Boot WireMock integration
  • Test coverage with JaCoCo — add plugin to Maven, generates coverage report. Aim for 70%+ on business logic
  • Mutation testing with PIT — checks if your tests actually catch bugs
Phase 7 — Production
Week 12–14 · ~50 hrs
24
DevOps
Docker — Containerize Your Application
⏱ 4 days
Dockerfile, Multi-stage Builds, docker-compose, Networking
Must Know
  • Spring Boot Dockerfile: FROM eclipse-temurin:21-jre-alpineCOPY target/*.jar app.jarENTRYPOINT ["java","-jar","app.jar"]
  • Multi-stage build — Stage 1: FROM maven:3.9-jdk-21 to build. Stage 2: FROM eclipse-temurin:21-jre-alpine to run. Final image has no build tools (smaller) INTERVIEW
  • Layer caching: COPY pom.xml → RUN mvn dependency:go-offline → COPY src → RUN mvn package. Dependencies cached if pom.xml unchanged
  • Key commands: docker build -t myapp:1.0 ., docker run -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod myapp, docker ps, docker logs -f, docker exec -it container bash, docker stop, docker rm
  • docker-compose.yml — define app + postgres + redis together. Startup order with depends_on + healthcheck
  • Environment variables: use env_file: .env in compose for secrets
  • Volumes: persist PostgreSQL data: volumes: - postgres_data:/var/lib/postgresql/data
  • Docker networking: containers in same compose network communicate by service name: jdbc:postgresql://postgres:5432/mydb
  • .dockerignore — exclude target/, .git, etc. from build context
  • JVM in containers: always set -Xmx in JAVA_OPTS. Container memory limits != JVM heap
25
DevOps
CI/CD — GitHub Actions Pipeline
⏱ 3 days
GitHub Actions — Build, Test, Docker, Deploy Pipeline
Must Know
  • Workflow file: .github/workflows/ci.yml. Triggers: push, pull_request, schedule, workflow_dispatch
  • Jobs and steps: checkout → setup-java → cache maven deps → mvn test → docker build → push to registry → deploy
  • Matrix strategy — run same job across multiple Java versions
  • GitHub Secrets — store DB_PASSWORD, DOCKER_HUB_TOKEN, AWS credentials. Access as ${{ secrets.MY_SECRET }}
  • Service containers — run PostgreSQL in CI for integration tests
  • Caching Maven dependencies: actions/cache for ~/.m2/repository → faster builds
  • Branch protection rules — require CI pass before merge to main
  • Environments: define staging and prod environments with required reviewers
  • Reusable workflows — define once, call from multiple workflows
  • Artifact upload/download — pass JAR between jobs
26
DevOps
Cloud — AWS Essentials for Java Developers
⏱ 5 days
IAM, EC2, RDS, S3, ECR, ECS Fargate, VPC
Must Know
  • IAM — users, roles, policies. Least privilege principle. Never use root account. IAM roles for EC2/ECS INTERVIEW
  • EC2 — virtual machine. Security groups (firewall rules). SSH key pair. t2.micro is free tier
  • RDS — managed PostgreSQL. Multi-AZ for HA. Read replicas for scale. Automated backups
  • S3 — object storage. Buckets, objects, keys. Use for file uploads, static assets, backups. Pre-signed URLs for secure upload from client
  • ECR — Docker image registry. Push images from CI, pull in ECS
  • ECS Fargate — serverless containers. Task definition, Service, Cluster. No EC2 management
  • VPC — private network. Public subnets (load balancer), private subnets (app, DB). NAT Gateway for outbound from private
  • Application Load Balancer — HTTPS termination, route traffic to ECS tasks, health checks
  • AWS Secrets Manager — store DB credentials, API keys. Spring Boot can read from Secrets Manager
  • AWS Free Tier: EC2 t2.micro 750hrs/month, RDS 750hrs. Set billing alarm at $10!
  • SQS — managed message queue (alternative to Kafka for simple cases)
  • Parameter Store — store config values (cheaper than Secrets Manager for non-secrets)
27
DevOps
Monitoring, Logging & Observability
⏱ 3 days
Structured Logging, Micrometer, Prometheus, Distributed Tracing
Important
  • Three pillars of observability: Logs (what happened), Metrics (how much/often), Traces (how long, where) INTERVIEW
  • Logback (Spring default): logback-spring.xml config. Log levels: TRACE < DEBUG < INFO < WARN < ERROR
  • Structured JSON logging — use logstash-logback-encoder. Parse-able by Elasticsearch/CloudWatch
  • MDC (Mapped Diagnostic Context) — add requestId, userId to all log lines in a request automatically
  • Correlation ID — add X-Correlation-ID header, propagate through services for request tracing
  • Micrometer — Spring's metrics facade. Exports to Prometheus, DataDog, etc. via Spring Actuator
  • Prometheus + Grafana — scrape metrics from /actuator/prometheus, visualize dashboards
  • Micrometer Tracing (Spring 3) — distributed tracing. Integrates with Zipkin or Jaeger
  • @Timed — annotate methods to automatically collect timing metrics
  • Custom metrics: Counter, Gauge, Timer, DistributionSummary via MeterRegistry
  • AWS CloudWatch — logs and metrics in AWS. CloudWatch Alarms for alerts
Phase 8 — Advanced Topics
Week 14–16 · ~60 hrs
28
Advanced
Redis — Caching, Sessions, Rate Limiting
⏱ 4 days
Redis Data Structures, Spring Cache, Patterns
Important
  • Redis data structures: String (simple key-value), Hash (object fields), List (queue/stack), Set (unique members), Sorted Set (scored ranking), HyperLogLog (cardinality), Pub/Sub (messaging)
  • TTL (Time To Live): EXPIRE key 3600 — auto-expire keys
  • Atomic operations: INCR, INCRBY, SETNX (set if not exists), GETSET
  • Spring Cache abstraction: @EnableCaching → @Cacheable("users") on service method → @CacheEvict on update/delete → @CachePut to update cache
  • RedisCacheManager — configure TTL per cache, serialization (use JSON not Java serialization)
  • Cache-aside pattern: check cache → miss → query DB → populate cache → return INTERVIEW
  • Write-through: write to cache and DB simultaneously
  • Cache stampede — many requests miss cache simultaneously → DB overload. Fix: locking or probabilistic early expiry
  • Cache invalidation strategies: TTL expiry, event-driven eviction, cache aside INTERVIEW
  • Session storage: Spring Session + Redis — store HTTP sessions in Redis for horizontal scaling
  • Rate limiting with Redis: sliding window using ZADD + ZRANGE, or token bucket with INCR
  • Bucket4j — rate limiting library with Redis backend for distributed limiting
  • Redis pub/sub — lightweight messaging: PUBLISH channel message, SUBSCRIBE channel
  • RedisTemplate vs StringRedisTemplate — StringRedisTemplate for String keys/values (simpler)
🎯 Interview

"How would you implement caching in Spring?" and "What's the cache-aside pattern?" and "What are the challenges of caching?" (invalidation, stampede, consistency with DB). Common system design questions too.

29
Advanced
Apache Kafka — Async Messaging & Event Streaming
⏱ 5 days
Kafka Architecture, Spring Kafka, Patterns
Important
  • Why Kafka: decouple producers from consumers. Async processing. Replay events. Fan-out to multiple consumers
  • Core concepts: Topic (category), Partition (parallelism unit), Offset (position in partition), Consumer Group (parallel consumers) INTERVIEW
  • Producer — sends to topic. Key determines partition (same key → same partition → order guaranteed)
  • Consumer Group — each partition consumed by one consumer in group. Scale consumers by adding to group
  • Broker — Kafka server. Replication factor for fault tolerance
  • Retention — messages kept for configurable period (7 days default). Can replay
  • KafkaTemplate — send messages: kafkaTemplate.send("orders", key, orderEvent)
  • @KafkaListener — consume: @KafkaListener(topics="orders", groupId="order-service")
  • Serialization: use JSON serializer (JsonSerializer/JsonDeserializer). Configure via @KafkaListener or properties
  • At-least-once delivery — default. Consumer may reprocess. Make consumers idempotent INTERVIEW
  • Exactly-once (transactions) — Kafka transactions + idempotent producer. Complex
  • Dead Letter Topic (DLT) — failed messages go to orders-dlt after retry exhausted
  • Retry + backoff: @RetryableTopic for automatic retry with exponential backoff
  • Outbox Pattern — write event to outbox table in same transaction as business data. Separate process publishes to Kafka. Guarantees consistency INTERVIEW
  • Consumer lag — how far behind consumers are from latest offset. Monitor this in production
🎯 Interview

"How does Kafka differ from RabbitMQ?" — Kafka = log-based, durable, replayable, high throughput. RabbitMQ = message-broker, routed, messages deleted on consume, complex routing rules. Also: "Explain the outbox pattern."

30
Advanced
Microservices — Architecture & Patterns
⏱ 5 days
Microservices Patterns — Gateway, Circuit Breaker, Service Discovery, Saga
Senior Level
  • Monolith vs microservices: start monolith, extract services when you hit clear boundaries. Don't over-engineer from day one INTERVIEW
  • API Gateway — single entry point. Handles: routing, auth, rate limiting, SSL termination. Spring Cloud Gateway
  • Service Discovery — services register themselves, others find them by name. Eureka (Spring Cloud), Consul, Kubernetes DNS
  • Load balancing — Spring Cloud LoadBalancer (replaces Ribbon). Client-side load balancing
  • Circuit Breaker (Resilience4j) — prevent cascade failures. States: CLOSED (normal) → OPEN (failing, reject requests) → HALF_OPEN (test one request). @CircuitBreaker annotation INTERVIEW
  • Fallback — return cached data or default response when circuit is open
  • Retry with @Retry — retry failed calls with exponential backoff
  • Rate Limiter with @RateLimiter — protect downstream services
  • RestTemplate vs WebClient vs OpenFeign — Feign is declarative HTTP client: @FeignClient("user-service") INTERVIEW
  • Distributed tracing — trace ID propagated through services. Micrometer Tracing + Zipkin/Jaeger
  • Saga pattern — manage distributed transactions across services. Choreography (events) vs Orchestration (coordinator) INTERVIEW
  • CQRS — Command Query Responsibility Segregation: separate read/write models. Read from replica, write to primary
  • Event Sourcing — store events not state. Rebuild state by replaying events
  • gRPC — binary protocol, faster than REST for inter-service. Protocol Buffers for schema
31
Advanced
System Design — Interview Preparation
⏱ 5+ days · Ongoing practice
System Design Concepts — CAP, Scaling, Patterns
Interview Critical
  • CAP Theorem: Consistency, Availability, Partition Tolerance — can only guarantee 2 of 3 in distributed system INTERVIEW
  • Horizontal scaling (scale out) — add more servers. vs Vertical scaling (scale up) — bigger server
  • Stateless services — any instance can handle any request. Required for horizontal scaling. Store state in Redis/DB not in-memory
  • Load balancing algorithms: Round Robin, Least Connections, IP Hash (sticky sessions), Weighted
  • CDN — cache static assets at edge. Reduce latency globally
  • Rate limiting: Token Bucket (burst allowed), Fixed Window, Sliding Window, Leaky Bucket INTERVIEW
  • Database scaling: Read replicas (read from replica, write to primary), Sharding (partition data by key), Connection pooling
  • Consistent hashing — distribute keys across nodes with minimal redistribution when nodes added/removed
  • Message queues — decouple components, handle traffic spikes, async processing
  • Design URL shortener: Base62 encoding, Redis cache for popular URLs, consistent hashing for distribution INTERVIEW
  • Design Twitter feed: Fan-out on write vs fan-out on read. Celebrity problem. Hybrid approach INTERVIEW
  • Design notification service: Kafka for async, multiple consumers per channel (email, SMS, push) INTERVIEW
🏗 Final Capstone Project

Build an e-commerce backend: Products, Orders, Users, Payments. Use: Spring Boot + PostgreSQL + Redis (cart/sessions) + Kafka (order events) + Docker + GitHub Actions CI/CD + JWT auth + Testcontainers. This project is your portfolio anchor.

Loading...