Skip to main content
Open Source · Apache 2.0 · v1.0.7

Saga orchestration for Spring Boot.Compensate failures automatically, without the infrastructure overhead.

Sagaweaw automatically compensates what it can't complete — running on the PostgreSQL you already have. No new cluster. No new concepts.

Java 17+·Kotlin·Spring Boot 4.x·PostgreSQL · MySQL · H2·Zero extra infrastructure
Every distributed system team hits this

A transaction started,
got halfway, and stopped.

Now you have inconsistent state across services. The payment was charged, the inventory is locked, but there's no order to show for it.

Someone writes a recovery script. Another person gets paged. A support ticket appears. And this happens again next week.

refund() runs automatically — $127.00 returned
release() runs automatically — 2 units unlocked
No on-call alert. No recovery script. No 2am ticket.
production · order-service · 02:47 AM
02:41:03POST /charge — $127.00 charged to card
02:41:04POST /inventory — 2 units reserved
02:41:09POST /shipping — 503 Service Unavailable
02:41:09order #f3a9b2c1 stuck in EXECUTING
02:41:10🔔PagerDuty alert — on-call engineer paged
With Sagaweaw, instead:
02:41:09compensating charge-payment → refund()
02:41:09compensating reserve-inventory → release()
02:41:10saga #f3a9b2c1 COMPENSATED — no data leaked
The solution

Write the business logic. Sagaweaw handles the rest.

  • Compensation runs in reverse order, automatically
  • Exponential backoff retry, per step
  • Full audit trail in your own database
  • OpenTelemetry spans — zero config
  • One Spring Boot dependency — that's it
See the full quickstart →
OrderSaga.java
return saga
    .step("reserve-inventory")
        .invoke(ctx -> inventory.reserve(ctx.itemId()))
        .compensate(ctx -> inventory.release(ctx.itemId()))

    .step("charge-payment")
        .invoke(ctx -> payment.charge(ctx.amount()))
        .compensate(ctx -> payment.refund(ctx.chargeId()))
        .retryPolicy(exponential(3, Duration.ofSeconds(5)))

    .step("create-shipment")
        .invoke(ctx -> shipping.schedule(ctx.orderId()))
        .compensate(ctx -> shipping.cancel(ctx.orderId()))

    .build();
How it works

Automatic compensation

If any step fails, Sagaweaw executes compensations in reverse order — automatically. No data is left behind.

  • Exponential, fixed, or infinite retry per step
  • Durable state — survives crashes and restarts
  • Pivot point — configurable point of no return
  • Dead letters for surgical manual intervention
See the lifecycle →
reserve-inventory
charge-payment
create-shipment
 

See every saga, in real time

The embedded dashboard is your debug lens — live feed, step timeline, retry queue, dead letters, business ID search, and stuck saga detection. All on the port you choose.

localhost:8484/sagaweaw
Sagaweaw Dashboard — Feed

Plays well with what you already use

No new tools to learn. Metrics in Prometheus, traces in your OTel backend, logs with MDC — the database you already have. Zero new infrastructure.

Spring Boot
Auto-configured
Kotlin
sagaweaw-kotlin DSL
PostgreSQL
MySQL · H2
Prometheus
Auto scraping
Grafana
Template included
OpenTelemetry
Jaeger · Tempo · DD
Micrometer
Native instrumentation
MDC / Logback
Enriched logs
Webhooks
Slack · Discord · PD

Add spring-boot-starter-opentelemetry and saga spans appear automatically in your OTel backend. See docs →

Up and running in 5 minutes

One dependency. No new cluster. No boilerplate.

1

Add the dependency

sagaweaw-spring-boot-starter
2

Write your saga

@Saga + SagaDefinition<T>
3

Start it

sagaManager.start(context)
Open Source · Apache 2.0

Ready to stop writing recovery scripts?

Free forever. No lock-in. No external server. Just add the dependency.