resonate-external-system-of-record-pattern-go — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited resonate-external-system-of-record-pattern-go (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Pre-release caveat. The Go SDK has no semver-tagged release yet —go get …@latestresolves to a pseudo-version; pin a commit for stability. APIs may change before the first tag is cut. Every code block here is verified againstdevelop/go.mdx; there is no Go system-of-record example repo yet, so all snippets use only documented SDK surface at commit22076134651f.
For the language-agnostic framing and the "Write Last, Read First" mental model, see resonate-external-system-of-record-pattern-typescript. This skill translates that model to idiomatic Go: explicit (T, error) returns, option structs, and ctx.Run-based checkpointing without a separate dependency-injection mechanism.
The core contract is simple: one system owns the truth. Resonate coordinates the workflow and guarantees at-least-once execution; the external system enforces consistency through its own primitives — idempotency keys, upserts, conditional writes, ledger deduplication.
Do not use this pattern when all writes live inside a single ACID transaction scope — just use the transaction.
ctx.RunThis is the entire reason the pattern exists.
Whenever a workflow suspends and resumes (after a ctx.Sleep, a remote ctx.RPC, or a pending ctx.Promise), the entire workflow body re-executes from the top. Durable child promises short-circuit steps that already settled — the external call is not re-fired, and the stored result is returned directly. But any external call that is NOT wrapped in a ctx.Run will execute again on every replay, producing double-writes.
Rule: every read from or write to the external SoR must be inside its own `ctx.Run` leaf. A bare HTTP call or DB write in workflow code will fire once per replay.
// BAD — fires on every replay, may charge the card twice
func placeOrder(ctx *resonate.Context, args OrderArgs) (string, error) {
chargeID, err := stripe.Charge(args.AmountCents, args.CardToken) // replay fires this again
if err != nil {
return "", err
}
// ...
}
// GOOD — checkpointed; on replay the stored chargeID is returned, Stripe is not called again
func placeOrder(ctx *resonate.Context, args OrderArgs) (string, error) {
f, err := ctx.Run(chargeCard, args)
if err != nil {
return "", err
}
var chargeID string
if err := f.Await(&chargeID); err != nil {
return "", err
}
// ...
}ctx.ID()A ctx.Run step can re-execute on retry before it settles (Resonate delivers at-least-once). The SoR must be addressed idempotently so a duplicate call is harmless.
Derive stable keys from ctx.ID(), ctx.OriginID(), or stable workflow args — never from time.Now() or rand, which produce different values across replays and produce different keys, defeating deduplication.
type ChargeArgs struct {
OrderID string `json:"order_id"`
AmountCents int64 `json:"amount_cents"`
CardToken string `json:"card_token"`
}
// chargeCard is called via ctx.Run — it may execute more than once before settling.
// The idempotency key is derived from the stable order ID, not wall-clock time.
func chargeCard(args ChargeArgs) (string, error) {
idempotencyKey := "charge:" + args.OrderID // stable across retries
req, err := http.NewRequest("POST", "https://api.stripe.com/v1/charges", encodeForm(map[string]string{
"amount": fmt.Sprintf("%d", args.AmountCents),
"currency": "usd",
"source": args.CardToken,
}))
if err != nil {
return "", err
}
req.Header.Set("Idempotency-Key", idempotencyKey)
// ... execute request, parse response
return chargeID, nil
}Three sequential SoR interactions, each in its own ctx.Run. Any step that has already settled short-circuits on replay; no external system is hit twice.
type OrderArgs struct {
OrderID string `json:"order_id"`
SKU string `json:"sku"`
Quantity int `json:"quantity"`
AmountCents int64 `json:"amount_cents"`
CardToken string `json:"card_token"`
}
type ReserveArgs struct {
OrderID string `json:"order_id"`
SKU string `json:"sku"`
Quantity int `json:"quantity"`
}
type ChargeArgs struct {
OrderID string `json:"order_id"`
AmountCents int64 `json:"amount_cents"`
CardToken string `json:"card_token"`
}
type RecordArgs struct {
OrderID string `json:"order_id"`
ChargeID string `json:"charge_id"`
}
// recordOrder writes the finalized order to the SoR. Idempotent via ON CONFLICT
// DO NOTHING keyed on OrderID, so a replay-retry never double-records.
func recordOrder(_ *resonate.Context, args RecordArgs) (struct{}, error) {
_ = args // INSERT ... ON CONFLICT (order_id) DO NOTHING
return struct{}{}, nil
}
// createOrder orchestrates three idempotent SoR steps.
// Each ctx.Run is checkpointed: on replay, settled steps return their stored
// result without touching the external system.
func createOrder(ctx *resonate.Context, args OrderArgs) (string, error) {
// Step 1 — reserve inventory; idempotent via ON CONFLICT in the DB
fReserve, err := ctx.Run(reserveInventory, ReserveArgs{
OrderID: args.OrderID,
SKU: args.SKU,
Quantity: args.Quantity,
})
if err != nil {
return "", err
}
var reservationID string
if err := fReserve.Await(&reservationID); err != nil {
return "", err
}
// Step 2 — charge payment; idempotent via Stripe idempotency key
fCharge, err := ctx.Run(chargeCard, ChargeArgs{
OrderID: args.OrderID,
AmountCents: args.AmountCents,
CardToken: args.CardToken,
}, resonate.RunOpts{
RetryPolicy: resonate.ExponentialRetry{
MaxAttempts: 5,
Base: 100 * time.Millisecond,
Max: 30 * time.Second,
Jitter: true,
},
})
if err != nil {
return "", err
}
var chargeID string
if err := fCharge.Await(&chargeID); err != nil {
return "", err
}
// Step 3 — record the order in the SoR DB; idempotent via ON CONFLICT DO NOTHING
fRecord, err := ctx.Run(recordOrder, RecordArgs{OrderID: args.OrderID, ChargeID: chargeID})
if err != nil {
return "", err
}
if err := fRecord.Await(nil); err != nil {
return "", err
}
return args.OrderID, nil
}A common SoR pattern is: read current state, branch on it, then apply a mutation. Both the read and the write must be in separate ctx.Run calls. Reading the SoR in bare workflow code is unsafe — on replay the bare read fires again and may observe a different value (e.g., another process updated the account between the first run and the replay).
type AccountArgs struct {
AccountID string `json:"account_id"`
Delta int64 `json:"delta"`
}
type AccountState struct {
Balance int64 `json:"balance"`
Status string `json:"status"`
}
// adjustBalance reads account state as a checkpointed step, branches in plain
// Go code (no SoR access here), then applies the mutation in another step.
func adjustBalance(ctx *resonate.Context, args AccountArgs) (int64, error) {
// Checkpointed read — on replay returns the stored snapshot, not a fresh DB hit
fState, err := ctx.Run(getAccountState, args.AccountID)
if err != nil {
return 0, err
}
var state AccountState
if err := fState.Await(&state); err != nil {
return 0, err
}
// Branch in plain workflow code — no external calls here
if state.Status == "frozen" {
return 0, resonate.NewNonRetryable(fmt.Errorf("account %s is frozen", args.AccountID))
}
if state.Balance+args.Delta < 0 {
return 0, resonate.NewNonRetryable(fmt.Errorf("insufficient funds"))
}
// Checkpointed write — idempotent conditional update keyed on account ID + delta
idempotencyKey := fmt.Sprintf("%s:%s:adjust", args.AccountID, ctx.ID())
fApply, err := ctx.Run(applyBalanceDelta, ApplyArgs{
AccountID: args.AccountID,
Delta: args.Delta,
IdempotencyKey: idempotencyKey,
})
if err != nil {
return 0, err
}
var newBalance int64
if err := fApply.Await(&newBalance); err != nil {
return 0, err
}
return newBalance, nil
}ctx.ID() is stable across replays, so the derived idempotencyKey is identical on every retry — the SoR deduplicates.
Use resonate.RunOpts{RetryPolicy: ...} to control per-step retry behaviour. The default (nil) is ExponentialRetry{MaxAttempts: 3, Base: 100ms, Max: 30s, Jitter: true}.
Wrap terminal SoR errors (validation failures, 4xx responses that will never succeed) with resonate.NewNonRetryable so the retry loop stops immediately:
func reserveInventory(args ReserveArgs) (string, error) {
// ... call inventory service
if statusCode == 400 {
// Bad request — retrying won't help
return "", resonate.NewNonRetryable(fmt.Errorf("invalid SKU %q", args.SKU))
}
if statusCode == 409 {
// Already reserved under this order ID — idempotent success
return existingReservationID, nil
}
// 5xx — transient, let the retry policy handle it
return "", fmt.Errorf("inventory service error: %d", statusCode)
}Result<T> enum or ? operator. Error paths are explicit if err != nil chains.ctx.get_dependency::<T>(). Pass clients/pools as closed-over values or construct them outside the workflow and reference them in the leaf closure. The checkpoint is the same — the leaf's return value is stored in the durable promise and returned on replay without re-executing.ctx.ID() or a deterministic hash of stable args. time.Now() and math/rand produce different values across replays — never use them to derive keys passed into a SoR.Await returns the wrapped error immediately.ctx.Run(fn, args, resonate.RunOpts{...}) — the options struct must be last; misplacing it passes it as the function argument.ctx.Run re-executes on every replay. Always wrap SoR interactions in a leaf.ctx.ID() or stable args.ctx.Run.resonate-saga-pattern-go.resonate-basic-durable-world-usage-go — ctx.Run, ctx.RPC, ctx.Sleep, option structs, RegisteredFunc.Runresonate-saga-pattern-go — when the SoR doesn't cover all steps and you need compensation across multiple servicesdurable-execution — foundational replay semantics; this pattern is checkpoint-centricresonate-external-system-of-record-pattern-typescript — same pattern, TS SDK; good for mental modelresonate-external-system-of-record-pattern-rust — same pattern, Rust SDK; type-dispatched DI contrast~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.