Files
antigravity-skills-reference/skills/dbos-golang/references/pattern-idempotency.md
Max dml 7e5abd504f feat: add DBOS skills for TypeScript, Python, and Go (#94)
Add three DBOS SDK skills with reference documentation for building
reliable, fault-tolerant applications with durable workflows.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 23:26:51 +01:00

1.9 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Use Workflow IDs for Idempotency MEDIUM Prevents duplicate side effects like double payments pattern, idempotency, workflow-id, deduplication

Use Workflow IDs for Idempotency

Assign a workflow ID to ensure a workflow executes only once, even if called multiple times. This prevents duplicate side effects like double payments.

Incorrect (no idempotency):

func processPayment(ctx dbos.DBOSContext, orderID string) (string, error) {
	_, err := dbos.RunAsStep(ctx, func(ctx context.Context) (string, error) {
		return chargeCard(orderID)
	}, dbos.WithStepName("chargeCard"))
	return "charged", err
}

// Multiple calls could charge the card multiple times!
dbos.RunWorkflow(ctx, processPayment, "order-123")
dbos.RunWorkflow(ctx, processPayment, "order-123") // Double charge!

Correct (with workflow ID):

func processPayment(ctx dbos.DBOSContext, orderID string) (string, error) {
	_, err := dbos.RunAsStep(ctx, func(ctx context.Context) (string, error) {
		return chargeCard(orderID)
	}, dbos.WithStepName("chargeCard"))
	return "charged", err
}

// Same workflow ID = only one execution
workflowID := fmt.Sprintf("payment-%s", orderID)
dbos.RunWorkflow(ctx, processPayment, "order-123",
	dbos.WithWorkflowID(workflowID),
)
dbos.RunWorkflow(ctx, processPayment, "order-123",
	dbos.WithWorkflowID(workflowID),
)
// Second call returns the result of the first execution

Access the current workflow ID inside a workflow:

func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
	currentID, err := dbos.GetWorkflowID(ctx)
	if err != nil {
		return "", err
	}
	fmt.Printf("Running workflow: %s\n", currentID)
	return input, nil
}

Workflow IDs must be globally unique for your application. If not set, a random UUID is generated.

Reference: Workflow IDs and Idempotency