Idempotency Keys
Relevant source files
The following files were used as context for generating this wiki page:
Idempotency keys ensure that an API operation executes at most once, even if the client retries the request. This mechanism prevents duplicate side effects in the event of network failures, timeouts, or other transient errors. Crucible implements idempotency through specific model traits and automatic client-side token management.
System Architecture
The idempotency system consists of three primary components: the service model definition, the generated SDK logic, and the server runtime.
- Modeling: Developers mark operations as
idempotentorreadonlyin the.crumodel. They may also designate a specific input member as anidempotencyToken. - SDK Generation: Generated clients include logic to detect these traits and automatically populate tokens.
- Server Runtime: The server uses the token to identify unique logical requests and cache responses to avoid redundant processing.
Sources: crates/crucible-codegen-common/src/describe.rs:446, crates/crucible-codegen-common/src/guide.rs:252-256
Idempotency Logic Flow
The following diagram illustrates how the client and server interact using an idempotency token during a retry scenario.
The diagram shows that the server recognizes the retry via the token and returns the previous result without re-executing backend logic.
Sources: crates/crucible-codegen-common/src/guide.rs:252-256, crates/crucible-codegen-docs/src/markdown.rs:693-698
Idempotency Tokens
An idempotency token is a unique string sent by the client to identify a specific request. If the client does not provide a value for a member marked as an idempotency token, the generated SDK automatically generates one.
Token Behavior
- Automatic Generation: SDKs generate a fresh token for every new call if the member is omitted.
- Persistence: The same generated token is reused for every retry attempt of that specific logical call.
- Manual Override: Callers can manually set the token to replay a specific logical request across different execution contexts or calls.
| Property | Description |
|---|---|
| Model Field | idempotencyToken |
| Data Type | String (typically) |
| Generation | Once per call; reused on attempts |
| Requirement | Service may refuse requests missing a token for specific operations |
Sources: crates/crucible-codegen-common/src/guide.rs:252-256, crates/crucible-codegen-docs/src/markdown.rs:693-698, crates/crucible-codegen-kotlin/src/lib.rs:242-246
Retry Safety and Rules
Crucible clients use idempotency information to determine if a failed request can be safely retried.
Safety Classification
Operations are classified into three safety levels for retries:
- Read-Only: Operations marked
readonlyare always safe to retry. - Idempotent: Operations marked
idempotentare always safe to retry. - Token-Based: Non-idempotent operations are only safe to retry if they carry an
idempotencyToken.
Automated Retry Decisions
The client runtime automatically retries requests with backoff under the following conditions:
- Throttling Errors: Always retried for any operation.
- Transient Failures: Transport failures, HTTP 500, 502, 503, and 504 are retried only for safe (idempotent/read-only/tokened) operations.
The flowchart summarizes the decision logic used by the client runtime to ensure data integrity during failures.
Sources: crates/crucible-codegen-common/src/guide.rs:252-256, crates/crucible-codegen-ruby/src/lib.rs:56-60
Implementation in SDKs
Generated SDKs provide documentation and helper logic for handling idempotency tokens across different languages.
Language-Specific Documentation
| Language | Implementation Detail |
|---|---|
| Kotlin | Notes that the token member is filled with a fresh value when omitted to ensure retries are safe. |
| Ruby | Uses idempotency_token fields and explains retry behavior in YARD documentation. |
| Go | Models idempotency status in the wireSchema and uses it during c.call execution. |
| Markdown Docs | Includes a standard note: "When calling the API directly, send a unique value... and the same value when retrying it." |
Sources: crates/crucible-codegen-kotlin/src/lib.rs:241-247, crates/crucible-codegen-ruby/src/lib.rs:56-60, crates/crucible-codegen-go/src/lib.rs:446-450, crates/crucible-codegen-docs/src/markdown.rs:693-698
Summary
Idempotency Keys in Crucible provide a robust safety net for distributed systems. By combining model-level metadata with automated SDK token management, the framework ensures that retries are both safe and efficient. This architecture protects the server from redundant processing while providing clients with a reliable mechanism to recover from transient network errors without risk of duplicating side effects.