Context IDs
Context IDs provide request and runtime scoping across the TWIN stack. They are used to carry identity and tenancy metadata through async execution, enforce route-level context rules, and derive storage partition keys.
AsyncLocalStorage
The context package stores request context in Node.js AsyncLocalStorage through ContextIdStore.
At request entry, the API server creates a mutable contextIds object and runs route processing inside ContextIdStore.run(contextIds, ...). This means all downstream service code can read the same active context with ContextIdStore.getContextIds() without passing context through every function signature.
Engine lifecycle execution also runs inside ContextIdStore.run(...) so startup and shutdown logic can use the configured context IDs consistently.
Context IDs: Async Propagation Through a Request
Default Keys and Value Derivation
The default key names come from ContextIdKeys:
nodetenantorganizationuser
The table below shows where values are populated.
| Key | Primary Source | How Value Is Derived |
|---|---|---|
node | Node runtime state | During node startup, configureContextIds reads state.nodeId and sets engine.addContextId(ContextIdKeys.Node, state.nodeId) when node identity is enabled. |
tenant | Node runtime state and tenant processor | Startup sets from state.nodeTenantId when tenant mode is enabled. In tenant-processor mode, request pre-processing resolves tenant from x-api-key (or query fallback) and writes contextIds[ContextIdKeys.Tenant]. |
organization | JWT claim | AuthHeaderProcessor verifies token and maps JWT org claim to contextIds[ContextIdKeys.Organization]. |
user | JWT claim | AuthHeaderProcessor verifies token and maps JWT sub claim to contextIds[ContextIdKeys.User]. |
Notes:
- Tenant-aware auth also validates that request tenant context and JWT
tidmatch. - The runtime key is
organizationin code; this corresponds to organisation scope in platform documentation.
Context ID Handlers and Short Forms
Context IDs can be transformed by handlers before partitioning.
DidContextIdHandlervalidates DID format and returns the DID id segment as the short value (hex ids are compacted to base64url).TenantIdContextIdHandlervalidates tenant id format and returns a compact base64url short form.
Engine context-key registration associates each key with required handler features, then binds the matching handler implementation into ContextIdHandlerFactory.
Handlers are registered only for keys intended for partitioning. Keys that are typically populated only after authentication, such as organization and user, are intentionally left without default handlers to avoid coupling storage partitioning to identity values that are not available during unauthenticated or pre-auth flows.
Full and Short Form Examples
The table below shows illustrative full values and their short forms as used for partitioning.
| Key | Example Full Form | Example Short Form | How Short Form Is Produced |
|---|---|---|---|
node | did:iota:0x8c3f4a5e8d9a7b6c | jD9KXo2ae2xdTj8qGwydjn9qW0w9Lh8K | DidContextIdHandler takes the DID id segment and compacts hex to base64url. |
tenant | 7f3a9c1e0b4d6f8a2c5e7b9d1a3c4e6f | fzqcHgtNb4osXnudGjxObw | TenantIdContextIdHandler converts 32-hex tenant id to base64url. |
organization | did:iota:0x1234567890abcdef | Not produced | No default context-id handler is registered for this key. |
user | did:iota:0xabcdefabcdefabcd | Not produced | No default context-id handler is registered for this key. |
When multiple keys are used for partitioning, ContextIdHelper.combinedContextKey(...) joins the short forms with /. For example:
- Keys:
node,tenant - Combined partition key:
jD9KXo2ae2xdTj8qGwydjn9qW0w9Lh8K/fzqcHgtNb4osXnudGjxObw
Data Partitioning
Many connectors support context-based partitioning through optional partitionContextIds settings. When configured, the connector:
- reads current context IDs using
ContextIdStore.getContextIds(), - derives a combined partition key via
ContextIdHelper.combinedContextKey(...), - uses that key to isolate stored data.
Examples:
- Entity storage connectors persist an internal
partitionIdand include it in get, set, remove, and query filtering. - Blob storage connectors compose keys as
<partitionKey>/<id>, with arootfallback where relevant.
Partition Key Derivation
Optional Partition IDs
Partition IDs are optional by design:
- If
partitionContextIdsis not configured, no context partition key is produced. - If no partition key is produced, storage operates in a non-partitioned scope.
- If partition keys are configured but required context IDs are missing, context guards fail early rather than silently crossing partitions.
This model supports both single-scope deployments and strict multi-scope isolation without changing application service contracts.
For details on how partitioning behaves across different storage backends, multi-tenant deployment models, and tenant management, see Data Partitioning and Multi-Tenant Architecture.