Skip to main content
skill CX Codex

spring-boot-saga-pattern — Claude Code skill: sagas in Spring Boot

A skill for distributed transactions in Spring Boot microservices: choreography and orchestration, compensating actions, Kafka, RabbitMQ, Axon.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-saga-pattern -a claude-code
Open on GitHub

What spring-boot-saga-pattern does

The skill walks you through splitting a distributed transaction into a chain of local transactions with compensations instead of two-phase commit. It starts with design: map the sequence of operations, then find a matching compensation for every forward step. Choreography suits a greenfield system with few participants; orchestration fits complex workflows that already exist.

From there it covers implementation: services with local ACID transactions, idempotent compensations, Kafka setup with an error handler, an orchestrator that persists saga state, and event handlers for the choreography path. Monitoring is its own step — saga duration, compensation count, failure rate and stuck sagas via Prometheus.

A compensation has to run safely more than once, so the skill points to database constraints or deduplication tables. Saga state belongs in persistent storage; without it a crashed service leaves the process unrecoverable. Inter-service calls get circuit breakers, and messages past their retry limit go to dead-letter queues.

What it helps with

  • break a distributed transaction into local steps with compensations
  • replace two-phase commit in a microservice setup
  • make a compensating transaction idempotent
  • pick choreography or orchestration for a given workflow
  • track stuck sagas with metrics and alerts

Example prompts for the agent

  • Design a saga for order placement: Order → Payment → Inventory → Shipment, with a compensation per step
  • Show me a Kafka saga orchestrator that persists state in SagaStateRepository
  • How do I keep refundPayment idempotent when payment.failed arrives twice?

How to install spring-boot-saga-pattern

1Skills CLI (Vercel)

npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-saga-pattern -a claude-code

2Manually: put the files in place

~/.claude/skills/spring-boot-saga-pattern/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/spring-boot-saga-pattern/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about spring-boot-saga-pattern

How do I install spring-boot-saga-pattern in Claude?

Run npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-saga-pattern -a claude-code. The skill lands in ~/.claude/skills/spring-boot-saga-pattern/SKILL.md.

What does spring-boot-saga-pattern do?

It describes distributed transactions in Spring Boot microservices using the Saga pattern: a sequence of local transactions plus compensating actions instead of two-phase commit.

Which message brokers are supported?

Kafka and RabbitMQ for event-driven choreography, Axon Framework for orchestration. For Kafka the skill includes a listener factory config with an error handler and asks for a transactional ID.

Source text

SKILL.md · MIT
---
name: spring-boot-saga-pattern
description: Provides distributed transaction patterns using the Saga Pattern for Spring Boot microservices. Use when implementing distributed transactions across services, handling compensating transactions, ensuring eventual consistency, or building choreography or orchestration-based sagas with Kafka, RabbitMQ, or Axon Framework.
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
---

# Spring Boot Saga Pattern

## Overview

Implements distributed transactions across microservices using the Saga Pattern. Replaces two-phase commit with a sequence of local transactions and compensating actions. Supports choreography (event-driven) and orchestration (centralized coordinator) approaches with Kafka, RabbitMQ, or Axon Framework.

## When to Use

- Building distributed transactions across multiple microservices
- Replacing two-phase commit (2PC) with a more scalable solution
- Handling transaction rollback when a service fails
- Ensuring eventual consistency in microservices architecture
- Implementing compensating transactions for failed operations
- Coordinating complex business processes spanning multiple services

**Trigger phrases**: distributed transactions, saga pattern, compensating transactions, microservices transaction, eventual consistency, rollback across services, orchestration pattern, choreography pattern

## Instructions

### 1. Design Transaction Flow

Map the sequence of operations and their compensating transactions:

```
Order → Payment → Inventory → Shipment
  ↓        ↓        ↓          ↓
Cancel  Refund   Release    Cancel
```

**Validation**: Verify every forward step has a corresponding compensation.

### 2. Choose Implementation Approach

| Approach | Use Case | Stack |
|----------|----------|-------|
| Choreography | Greenfield, few participants | Spring Cloud Stream + Kafka/RabbitMQ |
| Orchestration | Complex workflows, brownfield | Axon Framework, Eventuate Tram, Camunda |

**Validation**: Review team expertise and system complexity before choosing.

### 3. Implement Services with Local Transactions

Each service completes its local ACID transaction atomically:

```java
@Service
@RequiredArgsConstructor
public class OrderService {
    private final OrderRepository orderRepository;
    private final KafkaTemplate<String, Object> kafka;

    @Transactional
    public Order createOrder(CreateOrderCommand cmd) {
        Order order = orderRepository.save(new Order(cmd.orderId(), cmd.items()));
        kafka.send("order.created", new OrderCreatedEvent(order.getId(), order.getItems()));
        return order;
    }
}
```

**Validation**: Test that local transaction commits before event is published.

### 4. Implement Compensating Transactions

Every forward operation requires an idempotent compensation:

```java
@Service
@RequiredArgsConstructor
public class PaymentService {
    private final PaymentRepository paymentRepository;
    private final KafkaTemplate<String, Object> kafka;

    public void processPayment(PaymentRequest request) {
        Payment payment = paymentRepository.save(new Payment(request.orderId(), request.amount()));
        kafka.send("payment.processed", new PaymentProcessedEvent(payment.getId(), request.orderId()));
    }

    @Transactional
    public void refundPayment(String paymentId) {
        paymentRepository.findById(paymentId)
            .ifPresent(p -> {
                p.setStatus(REFUNDED);
                paymentRepository.save(p);
                kafka.send("payment.refunded", new PaymentRefundedEvent(paymentId));
            });
    }
}
```

**Validation**: Confirm compensation can execute safely multiple times (idempotency).

### 5. Set Up Message Broker

Configure Kafka with idempotent consumers:

```java
@Configuration
@EnableKafka
public class KafkaConfig {
    @Bean
    public ConcurrentKafkaListenerContainerFactory<String, Object> kafkaListenerContainerFactory(
            ConsumerFactory<String, Object> consumerFactory) {
        ConcurrentKafkaListenerContainerFactory<String, Object> factory =
            new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory);
        factory.setCommonErrorHandler(new DefaultErrorHandler());
        return factory;
    }
}
```

**Validation**: Enable transactional ID and verify exactly-once semantics.

### 6. Implement Saga Orchestrator (Orchestration Only)

```java
@Service
@RequiredArgsConstructor
public class OrderSagaOrchestrator {
    private final KafkaTemplate<String, Object> kafka;
    private final SagaStateRepository sagaStateRepo;

    public void startSaga(OrderRequest request) {
        String sagaId = UUID.randomUUID().toString();
        sagaStateRepo.save(new SagaState(sagaId, STARTED, LocalDateTime.now()));
        kafka.send("saga.order.start", new StartOrderSagaCommand(sagaId, request));
    }

    @KafkaListener(topics = "payment.failed")
    public void handlePaymentFailed(PaymentFailedEvent event) {
        kafka.send("order.compensate", new CompensateOrderCommand(event.getSagaId()));
        kafka.send("inventory.compensate", new ReleaseInventoryCommand(event.getSagaId()));
        sagaStateRepo.updateStatus(event.getSagaId(), FAILED);
    }
}
```

**Validation**: Verify saga state persists before sending commands. Check compensation triggers on each failure path.

### 7. Implement Event Handlers (Choreography Only)

```java
@Service
public class OrderEventHandler {
    private final OrderService orderService;
    private final KafkaTemplate<String, Object> kafka;

    @KafkaListener(topics = "payment.processed", groupId = "order-service")
    public void onPaymentProcessed(PaymentProcessedEvent event) {
        try {
            InventoryReservedEvent result = orderService.reserveInventory(event.toInventoryRequest());
            kafka.send("inventory.reserved", result);
        } catch (InsufficientInventoryException e) {
            kafka.send("inventory.insufficient", new InsufficientInventoryEvent(event.getOrderId(), event.getPaymentId()));
        }
    }
}
```

**Validation**: Test that each event handler correctly triggers the next step or compensation.

### 8. Add Monitoring and Observability

```java
@Configuration
public class SagaMetricsConfig {
    @Bean
    public MeterRegistry meterRegistry() {
        return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
    }
}
```

Track: saga execution duration, compensation count, failure rate, stuck sagas.

**Validation**: Set up alerts for sagas exceeding expected duration.

## Best Practices

**Design**:
- Make compensating transactions **idempotent** using database constraints or deduplication tables
- Use **immutable events** (Java records) to prevent accidental mutation
- Store saga state in persistent storage for recovery

**Error Handling**:
- Implement **circuit breakers** for inter-service calls
- Use **dead-letter queues** for messages exceeding retry limits
- Set appropriate **timeouts** per saga step (30s default, configurable)

**Monitoring**:
- Track saga status: PENDING, COMPLETED, COMPENSATING, FAILED
- Monitor compensation execution time
- Alert when sagas exceed SLA duration

## Constraints and Warnings

- Every forward transaction MUST have a corresponding compensating transaction
- Compensating transactions MUST be idempotent to handle retry scenarios
- Saga state MUST be persisted to handle failures and recovery
- Never use synchronous communication between saga participants
- Sagas provide eventual consistency, not strong consistency
- Test all failure scenarios including partial failures
- Consider Axon Framework or Eventuate for complex orchestrations
- Ensure message brokers are highly available

## Examples

### Choreography-Based Saga

```java
// Application.java
@SpringBootApplication
@EnableKafka
@EnableKafkaListeners
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

// Event Classes (immutable)
public record OrderCreatedEvent(String orderId, List<OrderItem> items) {}
public record PaymentProcessedEvent(String paymentId, String orderId) {}
public record InventoryReservedEvent(String reservationId, String orderId) {}
public record PaymentFailedEvent(String orderId, String reason) {}
public record InsufficientInventoryEvent(String orderId, String paymentId) {}

// OrderService with compensation
@Service
@RequiredArgsConstructor
public class OrderService {
    private final OrderRepository orderRepository;
    private final KafkaTemplate<String, Object> kafka;

    @KafkaListener(topics = "payment.failed", groupId = "order-service")
    public void handleCompensation(PaymentFailedEvent event) {
        orderRepository.findByOrderId(event.orderId())
            .ifPresent(order -> {
                order.setStatus(CANCELLED);
                orderRepository.save(order);
            });
    }
}
```

### Orchestration-Based Saga with Axon Framework

```java
// Command
@Aggregate
public class OrderAggregate {
    @AggregateIdentifier
    private String orderId;

    @CommandHandler
    public OrderAggregate(CreateOrderCommand cmd) {
        apply(new OrderCreatedEvent(cmd.orderId(), cmd.items()));
    }

    @EventSourcingHandler
    public void on(OrderCreatedEvent event) {
        this.orderId = event.orderId();
    }

    @CommandHandler
    public void handle(CancelOrderCommand cmd) {
        apply(new OrderCancelledEvent(cmd.orderId(), cmd.reason()));
    }
}
```

## References

- [Saga Pattern Definition](references/saga-pattern-definition.md)
- [Choreography Implementation](references/choreography-implementation.md)
- [Orchestration Implementation](references/orchestration-implementation.md)
- [Compensating Transactions](references/compensating-transactions.md)
- [State Management](references/state-management.md)
- [Error Handling and Retry](references/error-handling-retry.md)
- [Testing Strategies](references/testing-strategies.md)
- [Pitfalls and Solutions](references/pitfalls-solutions.md)
- [Examples](references/examples.md)

© giuseppe-trisciuoglio · MIT · giuseppe-trisciuoglio/developer-kit

Similar skills

All skills for Backend and APIs →

From the same set96

nextjs-app-router Patterns and code examples for Next.js 16+ App Router work, including components, actions, API handlers, caching and routing. CX Codex +1 3,900installs spring-boot-crud-patterns A skill that builds the whole CRUD layer for Spring Boot 3 services: aggregates, JPA repositories, DTOs and REST controllers in a feature-based layout. CX Codex +1 3,900installs typescript-security-review Reviews TypeScript and Node.js codebases for OWASP Top 10 vulnerabilities, leaked secrets, and authentication bugs. Useful before production releases in Express, NestJS, or Next.js apps. CX Codex +1 3,900installs prompt-engineering This skill helps write, debug, and test LLM prompts. Use it for few-shot examples, system prompts, reasoning workflows, and reusable templates. CX Codex +1 3,900installs unit-test-json-serialization A skill with patterns for unit testing JSON serialization and deserialization using Jackson and @JsonTest in Spring Boot. CX Codex +1 3,800installs unit-test-controller-layer Generates isolated MockMvc unit tests for Spring REST controllers with Mockito. Helps verify HTTP status codes, payload validation, and JsonPath assertions. CX Codex +1 3,800installs unit-test-parameterized A skill that turns one JUnit 5 test method into many runs over different inputs. Useful when you need boundary coverage without copy-pasting assertions. CX Codex +1 3,800installs nextjs-authentication A skill with ready authentication patterns for Next.js 15+ App Router on Auth.js 5: providers, route protection, sessions and roles. CX Codex +1 3,800installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor