In microservices, every network call can fail. A slow dependency can exhaust your thread pool, cascading into a full outage. Resilience4j provides the patterns to handle these failures gracefully — without hiding them. Setup <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot3</artifactId> <version>2.2.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> Circuit Breaker A circuit breaker wraps a remote call. When failures exceed a threshold, the circuit “opens” and calls fail immediately (without waiting for a timeout) — protecting your thread pool and giving the failing service time to recover.
Continue reading »Tutorial
264 posts in this section
Retry Logic: Handling Transient Failures Gracefully
Introduction Batch jobs interact with databases, REST APIs, and file systems — all of which fail transiently. A MySQL deadlock resolves itself in milliseconds. A network timeout to an external service clears up in seconds. Retrying these transient failures automatically is far better than failing the entire job and requiring a manual restart. Spring Batch has built-in retry support at the step level, integrated with its transaction management. This article covers everything you need to configure robust retry behaviour.
Continue reading »Role-Based Access Control with @PreAuthorize
Roles and permissions control what authenticated users can do. This article implements a complete RBAC system — from URL-level rules to method-level security and resource ownership checks. Roles vs Permissions Roles are coarse-grained groupings (USER, MANAGER, ADMIN). Permissions are fine-grained actions (READ_ORDERS, WRITE_PRODUCTS, DELETE_USERS). Assign permissions to roles: ADMIN → all permissions MANAGER → READ_ORDERS, WRITE_ORDERS, READ_PRODUCTS, WRITE_PRODUCTS USER → READ_OWN_ORDERS, WRITE_OWN_ORDERS, READ_PRODUCTS Model permissions as a typed enum: public enum Permission { // Order permissions READ_ORDERS, WRITE_ORDERS, DELETE_ORDERS, READ_OWN_ORDERS, WRITE_OWN_ORDERS, // Product permissions READ_PRODUCTS, WRITE_PRODUCTS, DELETE_PRODUCTS, // User management READ_USERS, WRITE_USERS, DELETE_USERS } public enum Role { USER(Set.
Continue reading »Rollback in Production: Tag-Based Strategies and CI Validation
Article 9 covered what rollback commands exist. This article covers how to make rollback reliable in production — where a slow or broken rollback costs real money and real users. The difference between knowing the commands and having a working rollback strategy is process: mandatory tagging, pre-generated rollback files, CI gates, and a decision tree that removes guesswork during an incident. Why Rollback Fails in Production Rollback failures in production share a small set of root causes:
Continue reading »Rollback Strategies: Automatic, Custom, Tag-Based, and Count-Based
Rollback is the thing you build at 2am when the deployment broke production. The problem is that 2am is exactly the wrong time to discover your rollback blocks are missing, incomplete, or untested. This article covers rollback from a strategy perspective: how Liquibase generates rollback, when you must write it yourself, how to handle change types that cannot be rolled back at all, and how to validate your rollback strategy in CI so it works when you need it.
Continue reading »Service Discovery with Eureka
In a microservices environment, services scale up and down dynamically. You can’t hardcode IP addresses — a service running on 10 pods today has 10 different addresses. Service discovery solves this: services register themselves, and clients look up live instances by name. What Service Discovery Does Without service discovery: Order Service → http://192.168.1.45:8081/api/inventory ← hardcoded, breaks when IP changes With service discovery: Order Service → "inventory-service" → Eureka → [192.168.1.45:8081, 192.
Continue reading »Skip Logic, Dead Letter Patterns, and Job Restart Strategies
Introduction Retry handles transient failures. Skip handles permanent ones — bad data rows, constraint violations, malformed records that will never succeed no matter how many times you retry. Skip logic lets your job continue processing good records while recording bad ones for human review. This article covers: Configuring skip for specific exception types Custom SkipPolicy for fine-grained control Dead-letter table pattern for tracking skipped items Stopping a job intentionally vs failing it Handling abandoned executions Designing jobs that restart safely after any failure Basic Skip Configuration return new StepBuilder("importOrdersStep", jobRepository) .
Continue reading »Spring AI: Build a RAG Application
Large language models know a lot — but not about your data. RAG (Retrieval-Augmented Generation) solves this: find the relevant context from your documents, inject it into the prompt, and let the model answer grounded in your data. This article builds a complete RAG API with Spring AI 2.0. What You’ll Build A Q&A API over your product documentation: User: "What's the return policy for electronics?" → Search vector store for relevant docs → Inject matching paragraphs into prompt → Claude/GPT answers based on your actual docs Without RAG: the LLM guesses or hallucinate your policy.
Continue reading »Spring Bean Scopes and Lifecycle
Every bean in the Spring container has a scope (how many instances exist and for how long) and a lifecycle (what happens when it’s created and destroyed). Understanding these prevents subtle bugs and lets you optimize resource usage. Bean Scopes Overview Scope Instances Available in singleton One per ApplicationContext All apps prototype New instance every time All apps request One per HTTP request Web apps session One per HTTP session Web apps application One per ServletContext Web apps Singleton (Default) By default, every Spring bean is a singleton — one instance per ApplicationContext.
Continue reading »Spring Boot + Spring Batch Setup: Your First Complete Batch Project
Article 2 showed how chunk processing works conceptually. This article sets up the real project you’ll build on for the rest of the series — complete Maven configuration, MySQL metadata tables, multiple ways to trigger jobs, and correct use of JobParameters. Everything in this article is production-ready from the start. Project Dependencies Add spring-boot-starter-batch to your Maven project. That one starter brings in everything you need. <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.
Continue reading »