Skip to content

IdempotencyBehaviorOptions

Defined in: packages/pipeline-idempotency/src/interfaces/idempotency-options.interface.ts:56

Per-handler idempotency options, shallow-merged over the constructor defaults.

Tenant/principal-scoped command idempotency

// Fails closed when the tenant or principal is missing and escapes every
// segment; never build a key with a template string.
const createOrderKey = createPartitionedIdempotencyKeyFactory({
action: 'order.create',
principal: (ctx) => ['user', ctx.items.get(CURRENT_USER_ID) as string],
operation: (ctx) => (ctx.request as CreateOrderCommand).idempotencyKey,
});
class CreateOrderHandler {
@pipeline.wrap({ kind: 'command' }, [IdempotencyBehavior, {
keyFactory: createOrderKey,
ttl: 24 * 60 * 60 * 1000,
}])
async handle(command: CreateOrderCommand) {}
}

optional fingerprint?: boolean

Defined in: packages/pipeline-idempotency/src/interfaces/idempotency-options.interface.ts:85

Hash the request payload and reject a later call that reuses the same key with a different body (422). Default true. Disable if your key already fully identifies the payload.


optional keyFactory?: IdempotencyKeyFactory

Defined in: packages/pipeline-idempotency/src/interfaces/idempotency-options.interface.ts:63

Derives the idempotency key from the request/context. Required for the behavior to do anything — without a key (or when it returns undefined) the handler runs normally. Include tenant/principal ownership whenever a replay would otherwise bypass handler-level authorization.


optional releaseOnError?: boolean

Defined in: packages/pipeline-idempotency/src/interfaces/idempotency-options.interface.ts:109

When the handler throws, release the key so the client can safely retry (true, default). Set false to keep the key claimed and surface a conflict on retry (favors strict at-most-once over retryability).


optional replayScopeFactory?: IdempotencyReplayScopeFactory

Defined in: packages/pipeline-idempotency/src/interfaces/idempotency-options.interface.ts:102

Binds replay to the caller’s authorization scope while keeping the operation key stable.

The digest is captured when the key is claimed and stored on the record. A later duplicate may only replay the stored response when its digest matches; a mismatch, or a record stored without one, raises IdempotencyConflictError with reason replay_scope (409). The record is neither deleted nor re-executed, so a permission change can never cause the side effect to run twice.

Configure it for any operation whose response or effect depends on the caller’s permissions. Without it, replay is bound only by the key and the payload fingerprint.


optional scope?: IdempotencyRequestKind[]

Defined in: packages/pipeline-idempotency/src/interfaces/idempotency-options.interface.ts:78

Which request kinds this policy applies to. Default ['command'] — queries are naturally idempotent and usually want @cqrs-ddd/pipeline-cache instead.


optional ttl?: number

Defined in: packages/pipeline-idempotency/src/interfaces/idempotency-options.interface.ts:71

How long a key is remembered, in milliseconds. After this window the key may be reused and a fresh execution occurs. Successful completion restarts the TTL for the replay record. Must be a positive safe integer. Default 86_400_000 (24h).