IndexedDB Sync Outbox
A durable client-side write outbox on IndexedDB, built on idb 8.0.3, that survives reload and drains to a server API. Reads are paged with getAllFromIndex over an exclusive-lower-bound IDBKeyRange rather than stepping a cursor, the mistake Nolan Lawson measured at 1194.2ms versus 702.8ms for 50,000 records in Chrome and 11ms versus 1ms for 100 records in Safari. The drain loop is split across two transactions because an IndexedDB transaction auto-commits the moment it yields to the event loop, so it reads a batch, lets that transaction close, POSTs, then opens a fresh readwrite transaction to delete or mark-failed. Retries are counted per record with a dead-letter status, transport failures stop the loop instead of burning attempts on every record behind them, and 4xx responses are treated as permanent. Delivery is at-least-once by construction, so every record carries an Idempotency-Key the server dedupes on.
npx shadcn@latest add https://ui.aryank.space/r/indexeddb-sync-outbox.jsonInstalls from ui.aryank.space. To add it by hand, copy the files in Files below, or register the @compronents namespace via the docs.
Client writes land in a durable IndexedDB outbox that survives reload; a paged drain walks the queue to the server in order, and a failed row waits for the next drain instead of being lost.