DaxStore — Amazon DynamoDB Accelerator (DAX)
Read this page in the documentation
DaxStore — Amazon DynamoDB Accelerator (DAX) Overview Amazon DynamoDB Accelerator (DAX) is a fully managed, in-memory, write-through cache for Amazon DynamoDB. It is not a standalone database — it is a DynamoDB cache that speaks the DynamoDB wire API, so the amazon-dax-client driver is a drop-in replacement for the low-level AWS.DynamoDB client (getItem/putItem/deleteItem/scan, each returning a request object with a .promise()). Because none of that fits the SQL-shaped Dialect interface, DaxStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch — and maps a simple edge-KV get/set/del/list/incr surface onto a single DynamoDB table used as a key-value bucket. Identity: Property | Value | --------- | -------------------- | name | 'dax' | library | 'amazon-dax-client'| The table is addressed by a partition-key attribute (keyAttr, default 'key') holding the KV key and a value attribute (valueAttr, default 'value') holding the string value. The wrapped operations: get(key) → getItem (Key = { <keyAttr>: { S: key } }) set(k,v) → putItem (Item = { <keyAttr>: {S:key}, <valueAttr>: {S:value} }) del(key) → deleteItem list(pref?) → scan (projects and returns the <keyAttr> of each item) incr(k,by?) → read-modify-write over getItem/putItem (non-atomic) Driver — lazy-loaded Uses amazon-dax-client. The driver is not a hard dependency: it is loaded lazily via require('amazon-dax-client') inside connect() (resolving mod.default ?? mod), so importing this module never requires amazon-dax-client to be installed unless a store is actually connected. Injected client DaxStoreOptions accepts a pre-built client implementing the DaxClient interface (a DynamoDB-style low-level client). When provided, connect() uses it directly and skips require('amazon-dax-client'). This is how the test suite injects a method-spy mock (no driver, no network). Values are serialized before writing: strings are stored verbatim; every other value is JSON.stringify'd, and stored as a DynamoDB string (S) attribute. Connection Build a store from connection options and call connect(): Connection options: Option | Type | Purpose | ----------- | ----------- | ------------------------------------------------------------------------------------------- | tableName | string | DynamoDB table used as the KV bucket (required). | keyAttr | string | Partition-key attribute holding the key. Defaults to 'key'. | valueAttr | string | Attribute holding the value. Defaults to 'value'. | ttlAttr | string | TTL attribute name used by set() options. Defaults to 'ttl'. | endpoints | string[] | DAX cluster endpoints (e.g. ['dax://...dax-clusters.us-east-1.amazonaws.com']). | region | string | AWS region. | client | DaxClient | Pre-built DAX client; when set, connect() uses it and skips require('amazon-dax-client'). | All options are optional (DaxStoreOptions = {}); tableName is required for operations to target a table (it falls back to '' when unset). Injected-client form Methods Each operation builds DynamoDB AttributeValue-shaped params and calls the client, awaiting .promise(). Driver failures are wrapped in a DatabaseError; using any method before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | ------------- | ----------------------------- | ------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Uses an injected client if provided, otherwise lazy-requires amazon-dax-client and builds an AmazonDaxClient from endpoints/region. Idempotent. Wraps failures in ConnectionError. | disconnect | disconnect(): Promise<void> | Clears the client and connection state. | isConnected | isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): DaxClient | Returns the underlying DAX (DynamoDB-compatible) client. Throws ConnectionError if not connected. | Key-value operations Method | Signature | DynamoDB call | Behavior | ------- | --------------------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------- | get | get(key: string): Promise<string \| null> | getItem | Reads a key. Returns the stored <valueAttr>.S string, or null if the item (or attribute) is missing. | set | set(key: string, value: unknown, options?: DaxSetOptions): Promise<void> | putItem | Writes value (serialized) as an S attribute. TTL: options.expiration is written to ttlAttr as absolute Unix seconds; otherwise options.ttl is written as floor(now/1000) + ttl. | del | del(key: string): Promise<void> | deleteItem | Deletes a key. | list | list(prefix?: string): Promise<string[]> | scan | Scans the table projecting only <keyAttr>; returns each item's key. A prefix adds a beginswith(#k, :p) filter. | incr | incr(key: string, by?: number): Promise<number> | getItem + putItem | Increments the numeric value at key by by (default 1). Non-atomic read-modify-write. | DaxSetOptions TTL requires DynamoDB TTL to be enabled on the table with a matching attribute name (ttlAttr). Example Verification status Unit / mock-verified only. The tests in tests/nosql/dax.test.ts inject a method-spy mock DynamoDB-style client (getItem/putItem/deleteItem/scan, each returning { promise() }) via DaxStoreOptions.client. The real amazon-dax-client package is not installed, and there is no DAX cluster and no network in the test run. What this proves: Each method builds the correct DynamoDB params with proper AttributeValue shapes: getItem/deleteItem with Key = { key: { S: 'k' } }, putItem with the serialized S value, and scan with ProjectionExpression '#k'. set serializes non-strings ({ a: 1 } → '{"a":1}') and writes a TTL N attribute from expiration ({ ttl: { N: '1700000000' } }). get returns the value string, or null when the item is missing; list projects and returns the key attribute, and adds a beginswith(#k, :p) filter for a prefix; incr performs a read-modify-write (getItem then putItem with the new value). Lifecycle: connect/idempotent-connect/disconnect, getClient returning the injected client, and ConnectionError before connect(). Error handling: driver failures (a rejected .promise()) wrapped in DatabaseError. What this does not prove: live execution against a real DAX cluster / DynamoDB. The command/param shapes are verified against the DynamoDB low-level API contract, but end-to-end execution over the wire has not been exercised here. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories