Production
Deploy Sagaweaw to production in 5 steps. No extra containers. No dashboard repo to clone. One environment variable.
1. Add the dependency
2. Write your sagas
3. Set one environment variable
4. Deploy normally
5. Open the dashboard in your browser
Step 1 — Add the dependency
// Gradle (Kotlin DSL)
implementation("dev.sagaweaw:sagaweaw-spring-boot-starter:1.0.12")
<!-- Maven -->
<dependency>
<groupId>dev.sagaweaw</groupId>
<artifactId>sagaweaw-spring-boot-starter</artifactId>
<version>1.0.12</version>
</dependency>
Kotlin DSL? Add sagaweaw-kotlin too — see the Kotlin guide →.
Step 2 — Write your sagas
Implement SagaDefinition, annotate with @Saga. See the Quickstart → for a full example.
Step 3 — Set one environment variable
Generate a strong token once and store it in your secret manager:
openssl rand -hex 32
# → e3b0c44298fc1c149afb...
Set it as an environment variable on your server (or in your .env / secret manager):
SAGAWEAW_TOKEN=<your-generated-token>
In application.properties, reference it:
sagaweaw.observability.token=${SAGAWEAW_TOKEN}
sagaweaw.kafka.enabled=false
Without SAGAWEAW_TOKEN, every observability endpoint returns 403. This is intentional — the dashboard is never exposed accidentally.
Step 4 — Deploy normally
Deploy your Spring Boot application as you always do. Sagaweaw requires no additional services.
What happens on first boot:
- Sagaweaw's embedded Flyway runs automatically
- Creates 5 tables in your existing database:
sagas,saga_steps,saga_events,outbox_messages,dead_letters - Uses a separate history table (
sagaweaw_schema_history) — never conflicts with your own Flyway migrations - Your sagas are registered and ready
You will see logs like:
Flyway Community Edition ... by Redgate
Database: jdbc:postgresql://... (PostgreSQL ...)
Successfully applied 2 migration(s) to schema "public" on schema history table "sagaweaw_schema_history"
Step 5 — Open the dashboard
Navigate to your API URL followed by /sagaweaw:
https://your-api.com/sagaweaw
You will see the login screen. Enter your SAGAWEAW_TOKEN and press Enter.
The dashboard shows:
- Live feed — every saga execution in real time
- Step timeline — per-saga step-by-step view with timing, retries, and context
- Dead letters — failed sagas with full error trace and one-click reprocess
- Metrics — volume, success rate, P50/P95 latency, stuck sagas
Fields annotated with @SagaMask on your context class are stored and displayed as [REDACTED]. Use it for tokens, PII, or any sensitive data your saga carries:
public record Context(
@SagaMask String customerEmail,
@SagaMask String paymentToken,
UUID orderId
) implements SagaContext { ... }
Wiring production traffic
@AutoStart and the trigger endpoint are for development. In production, call SagaManager.start() where the business event happens:
@Service
public class PaymentService {
private final SagaManager sagaManager;
public void processPayment(PaymentRequest req) {
sagaManager.start(PixPaymentSaga.class, new PixPaymentSaga.Context(
UUID.randomUUID().toString(),
req.getDictKey(),
req.getAmount(),
req.getPayerId()
));
}
}
Remove @AutoStart and sagaweaw.auto-start.enabled from your production profile.
Free tier limits in multi-instance deployments
The open-source version works correctly for single-instance deployments. With 2+ pods sharing the same database, the internal schedulers (retry, outbox relay, retention) have no distributed lock — multiple pods may process the same item simultaneously.
For single-pod production deployments (most use cases) this is not an issue.
For multi-pod deployments at scale, Sagaweaw Cloud adds managed distributed locking, a hosted dashboard accessible from anywhere without VPN, and multi-environment support.
Configuration reference
| Property | Default | Description |
|---|---|---|
sagaweaw.observability.token | — | Required. Token for dashboard and API access |
sagaweaw.kafka.enabled | true | Set false if not using Kafka |
sagaweaw.dashboard.mode | embedded | embedded serves at /sagaweaw; standalone expects Vite dev server |
sagaweaw.dashboard.path | /sagaweaw | URL path for embedded mode |
sagaweaw.flyway.enabled | true | Set false to manage schema manually |
sagaweaw.health.stuck-threshold-minutes | 15 | Minutes before a stuck saga trips the health indicator |
sagaweaw.alerts.webhook-url | — | Slack / PagerDuty / Teams webhook for dead letter alerts |
sagaweaw.data.retention-days | 0 | Archive completed sagas after N days (0 = never) |
sagaweaw.data.failed-retention-days | 90 | Keep failed sagas for N days (LGPD/PCI-DSS audit trail) |
Next steps
- Local development → — Testing with @AutoStart and the Vite dev server
- Observability → — Full API reference for the dashboard endpoints
- Integrations → — Prometheus, Grafana, OpenTelemetry