Before shipping it, separate protocol facts, product promises, and operating cost. Mixing those layers produces confident but incorrect decisions. IndexedDB transactions can auto-commit when no requests remain. Awaiting network work inside them causes inactive errors, while separate chunk and manifest transactions create crash windows.
Browser capability depends on version, permission, visibility, and device policy. Use capability detection and an explained fallback instead of treating one development machine as the product contract.
The parts that make the design practical
Turn the important choices into durable contracts: validate inputs, assign state ownership, define cleanup, and specify fallback for older peers. Later optimization must not change those semantics.
- Finish network reads outside the transaction; inside, issue chunk write, range merge, and state update together.
- Use task and chunk index as idempotent keys so duplicates do not increase received bytes.
- Use explicit schema migrations that preserve old data on failure and offer recovery or cleanup.
Persistence trust comes from data and index in one transaction, not a remembered percentage. Define crash invariants first.
Keep false assumptions out of production
Production failures often appear when two individually valid actions overlap. Inspect stale messages, duplicate effects, exhausted resources, and mixed versions instead of patching only the current stack frame.
- Manifest updates before chunk storage, so quota failure makes refresh skip missing data.
- A long transaction waits on network, blocks other work, and is aborted by the browser.
- Progress comes from memory rather than committed records and regresses after a crash.
What the release gate should inspect
Observe both endpoints, persisted records, and operational signals during verification. One button state or one successful response cannot prove the complete loop.
- Terminate the page around chunk write, range merge, and commit; verify invariants after restart.
- Write one chunk repeatedly, out of order, and concurrently; storage stays unique and progress counts once.
- Exhaust quota and fail a schema upgrade, ensuring actionable errors and intact old tasks.
Completion is not one passing path. Every terminal state reconciles, automation stays below user intent, and every operational cost has an explicit ceiling.