# Golem Atomic Block Effect

> Using atomic regions and durability controls in Effect-based Golem agents. Use when an @golemcloud/effect-golem project needs whole-region replay, Durability.atomically, persistence or idempotence modes, oplog replication, idempotency keys, or scoped retry policies.

- Skill: `golemcloud/golem-atomic-block-effect` (Agent Skill)
- Install (CLI): `npx skillmds@latest add golemcloud/golem-atomic-block-effect`
- Raw SKILL.md: https://api.skillmd.com/api/skills/golemcloud/golem-atomic-block-effect/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: golemcloud (https://skillmd.com/u/golemcloud)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/golemcloud/golem-atomic-block-effect

---


# Atomic Regions and Durability Controls in Effect Golem Agents

Golem agents are durable by default. Use these advanced controls only when replay behavior must
change for a specific group of externally observable effects. Import the Effect SDK API from the
package root; do not translate callback helpers from `@golemcloud/golem-ts-sdk`.

```typescript
import { Duration, Effect, Schema } from "effect";
import {
  FetchHttpClient,
  HttpClient,
  HttpClientRequest,
  HttpClientResponse,
} from "effect/unstable/http";
import { Durability, Retry } from "@golemcloud/effect-golem";
```

## Atomic Regions

`Durability.atomically` accepts an `Effect`, not a synchronous or async callback. If execution
fails after only part of the region completed, recovery re-executes the region from its begin
marker instead of replaying from the middle.

```typescript
const placeOrder = Durability.atomically(
  Effect.gen(function* () {
    const reservation = yield* reserveInventory(itemId, quantity);
    const charge = yield* chargePayment(customerId, price);
    return { reservation, charge };
  }),
);
```

`reserveInventory` and `chargePayment` above are assumed to return Effects. Yield every operation
inside the body so the atomic region controls their ordering and failure.

Use an atomic region for:

- two or more external effects that must replay together after a crash; or
- one external effect followed by validation that may fail, when that failure must cause the
  effect itself to run again instead of replaying its recorded response.

External effects can still be repeated. Atomicity here means **whole-region re-execution during
durable recovery**, not ACID isolation or rollback in the external system. Design remote operations
to tolerate duplicates or use a stable idempotency key.

An atomic region only controls one durable execution. It does not deduplicate a later, independent
invocation of the same method: that invocation runs the method, including work after the atomic
region, again. When validating a state-changing recovery example, start the atomic work once
against a fresh agent identity. Do not run it during build/deploy validation if a test harness will
start the same identity afterward.

### Atomic Outgoing HTTP Effects

Use Effect's `HttpClient` when the atomic region must call an external service. The stable request
ID in this example is supplied by the caller, and each state-changing remote operation gets a
distinct idempotency key so whole-region replay can safely repeat it:

```typescript
const record = (event: string, requestId: string) =>
  HttpClientRequest.post("https://effects.example.com/record").pipe(
    HttpClientRequest.setHeader("Idempotency-Key", `${requestId}:${event}`),
    HttpClientRequest.bodyJson({ event }),
    Effect.flatMap(HttpClient.execute),
    Effect.flatMap(HttpClientResponse.filterStatusOk),
    Effect.asVoid,
  );

const shouldRetry = (requestId: string) =>
  HttpClientRequest.get(
    `https://effects.example.com/decide?requestId=${encodeURIComponent(requestId)}`,
  ).pipe(
    HttpClient.execute,
    Effect.flatMap(HttpClientResponse.filterStatusOk),
    Effect.flatMap(HttpClientResponse.schemaBodyJson(Schema.Boolean)),
  );

const runAtomicWork = (requestId: string) =>
  Effect.gen(function* () {
    yield* Durability.atomically(
      Effect.gen(function* () {
        yield* record("a", requestId);
        yield* record("b", requestId);

        if (yield* shouldRetry(requestId)) {
          return yield* Effect.die(
            new Error("retry the complete atomic region"),
          );
        }

        yield* record("c", requestId);
      }),
    );

    yield* record("d", requestId);
  }).pipe(Effect.provide(FetchHttpClient.layer), Effect.orDie);
```

The remote service must actually deduplicate each stable key. Merely setting an idempotency header
does not make the operation idempotent. `FetchHttpClient.layer` provides the HTTP service at the
handler boundary, and HTTP transport, status, encoding, and decoding failures inside the region
all trigger the same atomic trap behavior as any other unsuccessful Effect. The read-only decision
must eventually change after the condition that caused the trap is repaired; an unchanged `true`
response makes recovery fail repeatedly.

### Failure Semantics

`Durability.atomically` has intentionally stronger failure behavior than a normal Effect scope:

1. On success it writes the matching end marker and returns the body's value.
2. On a typed failure, defect, or interruption it leaves the region open and invokes the host's
   uncatchable trap so durable recovery can retry the complete region.
3. An outer `Effect.catchAll`, `Effect.either`, or similar operator cannot handle a body failure and
   continue the same invocation after the region.

The trap-recovery guarantee is a worker execution guarantee, not a promise that the original HTTP,
RPC, or CLI caller waits for replay. Do not externally retry with a new invocation merely because
the first caller observed a failure: that would start the method again and can duplicate work after
the atomic region.

Use `Effect.fail` for a condition that should trigger this trap just as a defect does; the high-level
atomic combinator traps every unsuccessful exit. Do not put caller-visible business failures inside
an atomic region if the invocation should recover from them and continue normally.

### Failure-Path Verification Limit

The pinned SDK has unit tests proving that an unsuccessful body leaves its marker open and calls the
host trap, but its real-runtime integration test covers only a successful atomic region. It exposes
no public Effect that waits for trap recovery, reports the recovery attempt, or guarantees that the
original caller eventually receives the replayed result. A fire-and-forget typed call only confirms
host acceptance; it does not provide a completion handle for the trapped invocation.

Consequently, use a successful `Durability.atomically` body for portable end-to-end application
tests. Verify deliberate crash/recovery behavior with executor-specific worker status and oplog
tooling rather than making a normal awaited method or polling loop depend on the trap completing.
Keep deterministic failures out of production atomic bodies: if the condition is unchanged after
recovery, the region can fail repeatedly.

### What Atomic Regions Are Not

- Do not wrap ordinary `Ref` updates just to make in-memory state “transactional.” Durable replay
  already rebuilds agent state, and agents process invocations sequentially.
- Do not use atomic regions to reduce oplog size or speed up recovery. Use snapshot-based recovery
  for that purpose.
- Do not claim that nested regions are supported, rejected, flattened, or merged; the pinned SDK
  does not define or test nesting behavior.

## Manual Begin and End Markers

Prefer `Durability.atomically`. When imperative control is genuinely required, begin is an Effect
value and end is a function taking the returned `bigint` oplog index:

```typescript
const manuallyBracketed = Effect.gen(function* () {
  const begin = yield* Durability.beginOperation;
  const result = yield* performExternalWork;
  yield* Durability.endOperation(begin);
  return result;
});
```

Manual markers do not trap or pair themselves on failure. Never put `endOperation(begin)` in an
unconditional finalizer: closing the marker after failure commits the region instead of leaving it
open for recovery.

## Persistence Level

Persistence-level controls are primarily for Golem-specific libraries implementing custom durable
behavior, not ordinary application optimization. Prefer the scoped combinator, which restores the
previous level when the Effect exits:

```typescript
const result = Durability.withPersistenceLevel(
  Durability.PersistenceLevel.persistNothing,
  customDurabilityEffect,
);
```

Available values are:

| Value                                                  | Meaning                                                  |
| ------------------------------------------------------ | -------------------------------------------------------- |
| `Durability.PersistenceLevel.smart`                    | Default host-managed durable behavior                    |
| `Durability.PersistenceLevel.persistRemoteSideEffects` | Persist remote side effects for replay                   |
| `Durability.PersistenceLevel.persistNothing`           | No replay or state-restoration guarantee for the section |

`persistNothing` is not an oplog-size switch. Code using it must implement the required live/replay
behavior itself. For low-level integration work, `Durability.getPersistenceLevel` is an Effect
value and `Durability.setPersistenceLevel(level)` changes the host mode directly; ordinary code
should use `withPersistenceLevel` so restoration is scoped.

## Idempotence Mode

The host default is `true`. In that mode, side effects are treated as idempotent and Golem
guarantees at-least-once semantics. This does not make an inherently non-idempotent external
operation safe. Opt out only for a side effect where a duplicate is worse than a missing call:

```typescript
const atMostOnce = Durability.withIdempotenceMode(false, nonIdempotentEffect);
```

`false` selects at-most-once handling; the executor fails the agent when it cannot determine whether
the side effect already ran. The scoped combinator restores the prior mode. Low-level code can yield
`Durability.getIdempotenceMode` and call `Durability.setIdempotenceMode(value)`, but should not
manually change the mode when the scoped form is sufficient.

## Oplog Replication Barrier

Wait for the oplog to reach the requested replica count by yielding the Effect:

```typescript
const replicationBarrier = Effect.gen(function* () {
  yield* Durability.oplogCommit(3);
});
```

The replica count must be a safe integer from `0` through `255`; the SDK forwards that value. The
host waits for at least that many replicas, or its maximum replica count if fewer are available.
This is a replication barrier, not an atomic-region commit.

## Durable Idempotency Keys

`generateIdempotencyKey` is an Effect value, not a function:

```typescript
const makeRequest = Effect.gen(function* () {
  const key = yield* Durability.generateIdempotencyKey;
  return { key };
});
```

The host persists and commits the generated key, and replay returns that same key rather than
generating another one. The generated TypeScript value is a UUID record with `highBits` and
`lowBits` bigint fields, not a UUID string. Convert it explicitly at an external API boundary if
text is required.

## Scoped Retry Policies

Retry policy control belongs to the separate `Retry` namespace. Effect Golem manages named host
policies rather than replacing one anonymous global policy:

```typescript
const paymentRetry = Retry.NamedPolicy.named(
  "payment",
  Retry.Policy.periodic(Duration.seconds(1)),
);

const result = Retry.withPolicy(paymentRetry, paymentEffect);
```

`Retry.withPolicy` attempts to restore the previous policy with the same name, or remove the
temporary one, when the Effect exits; cleanup failures are ignored. Other named policies remain
active. The combinator temporarily changes the host-visible policy set—it does not retry the whole
Effect like `Effect.retry`. Do not substitute a local Effect retry schedule when durable,
host-visible retry behavior is required.

## Key Constraints

- Import `Durability` and `Retry` from `@golemcloud/effect-golem`; do not import internal host
  clients or layers.
- Normal `defineAgent(...).implement({ init, methods })` execution supplies the services required by these
  Effects. Do not manually provide SDK-internal layers in application code.
- Keep agent methods Effect-based; do not wrap `Durability.atomically` in an `async` callback.
- Prefer `Durability.atomically` over manual begin/end markers.
- Keep externally observable actions duplicate-safe because recovery may execute them again.
- Use Effect `HttpClient` with `FetchHttpClient.layer` for outgoing HTTP rather than wrapping raw
  `fetch` in `Effect.tryPromise`.
- Do not assume an awaited caller or fire-and-forget trigger can observe completion after an
  intentional atomic trap; use executor-specific recovery tooling for that test.

## Authoritative API Sources

- [`Durability` public exports](https://github.com/golemcloud/effect-golem/blob/4b75f5e4d3cc306c3df75050db93d93aaa379ec3/src/Durability.ts)
- [Atomic and durability-mode implementation](https://github.com/golemcloud/effect-golem/blob/4b75f5e4d3cc306c3df75050db93d93aaa379ec3/src/internal/durabilityMode.ts)
- [Durability tests](https://github.com/golemcloud/effect-golem/blob/4b75f5e4d3cc306c3df75050db93d93aaa379ec3/test/durability.test.ts)
- [`Retry` policy API](https://github.com/golemcloud/effect-golem/blob/4b75f5e4d3cc306c3df75050db93d93aaa379ec3/src/Retry.ts)
- [Effect HTTP client skill](../golem-make-http-request-effect/SKILL.md)

