Files
antigravity-skills-reference/skills/dbos-golang/references/advanced-patching.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

2.8 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Use Patching for Safe Workflow Upgrades LOW Safely deploy breaking workflow changes without disrupting in-progress workflows advanced, patching, upgrade, breaking-change

Use Patching for Safe Workflow Upgrades

Use dbos.Patch to safely deploy breaking changes to workflow code. Breaking changes alter which steps run or their order, which can cause recovery failures.

Incorrect (breaking change without patching):

// BEFORE: original workflow
func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
	result, _ := dbos.RunAsStep(ctx, foo, dbos.WithStepName("foo"))
	_, _ = dbos.RunAsStep(ctx, bar, dbos.WithStepName("bar"))
	return result, nil
}

// AFTER: breaking change - recovery will fail for in-progress workflows!
func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
	result, _ := dbos.RunAsStep(ctx, baz, dbos.WithStepName("baz")) // Changed step
	_, _ = dbos.RunAsStep(ctx, bar, dbos.WithStepName("bar"))
	return result, nil
}

Correct (using patch):

func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
	useBaz, err := dbos.Patch(ctx, "use-baz")
	if err != nil {
		return "", err
	}
	var result string
	if useBaz {
		result, _ = dbos.RunAsStep(ctx, baz, dbos.WithStepName("baz")) // New workflows
	} else {
		result, _ = dbos.RunAsStep(ctx, foo, dbos.WithStepName("foo")) // Old workflows
	}
	_, _ = dbos.RunAsStep(ctx, bar, dbos.WithStepName("bar"))
	return result, nil
}

dbos.Patch returns true for new workflows and false for workflows that started before the patch.

Deprecating patches (after all old workflows complete):

func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
	dbos.DeprecatePatch(ctx, "use-baz") // Always takes the new path
	result, _ := dbos.RunAsStep(ctx, baz, dbos.WithStepName("baz"))
	_, _ = dbos.RunAsStep(ctx, bar, dbos.WithStepName("bar"))
	return result, nil
}

Removing patches (after all workflows using DeprecatePatch complete):

func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
	result, _ := dbos.RunAsStep(ctx, baz, dbos.WithStepName("baz"))
	_, _ = dbos.RunAsStep(ctx, bar, dbos.WithStepName("bar"))
	return result, nil
}

Lifecycle: Patch() → deploy → wait for old workflows → DeprecatePatch() → deploy → wait → remove patch entirely.

Required configuration — patching must be explicitly enabled:

ctx, _ := dbos.NewDBOSContext(context.Background(), dbos.Config{
	AppName:        "my-app",
	DatabaseURL:    os.Getenv("DBOS_SYSTEM_DATABASE_URL"),
	EnablePatching: true, // Required for dbos.Patch and dbos.DeprecatePatch
})

Without EnablePatching: true, calls to dbos.Patch and dbos.DeprecatePatch will fail.

Reference: Patching