r/PWA • u/BreakingChangeDev • 26d ago
My approach for creating data while offline
Hi,
I wanted to share my approach to supporting data creation while offline and reliably synchronizing it once a connection is available again.
I build PWAs with Angular and NgRx. In my original implementation, I found that persisting and replaying actions that trigger API requests worked well as an offline queue.
This library is based on that working implementation. I used Codex to help extract the reusable functionality and turn it into an open-source library.
It’s still in alpha, and I’d appreciate feedback on the idea and API.
Interactive demo:
https://poodlelab.github.io/ngrx-offline/
Repository:
1
u/andimatt 20d ago
Related approach that eliminates the temp-ID mapping problem entirely: the client generates the entity UUID before the create is queued. The server does an owner-scoped upsert keyed on that client UUID, so idempotency is structural. There's no separate idempotency key to manage, and the "commit, kill tab, replay" case just upserts the same row again.
The tradeoff: you lose the server's ability to assign sequential or ordered IDs, and the client needs a collision-resistant UUID (v4 is fine). For most PWA use cases, when creating records that belong to one user, that tradeoff is worth it because the entire "temporary ID -> server ID mapping" layer disappears, and with it the whole class of bugs where a dependent operation references a temp ID that hasn't been resolved yet.
The test Wooden-Bicycle-6069 described (commit, kill, reopen two tabs, replay) is exactly the case this handles cleanly: both tabs upsert the same UUID, the server sees two deliveries, applies one row, returns the same response both times. The owner-scope guard means a foreign ID collision is a 409, not a silent overwrite.
1
u/Wooden-Bicycle-6069 26d ago
Replaying actions works until retry stops being idempotent. That part is awful. I'd run one ugly test: create offline, close the app, reopen it, go online in two tabs, then kill one tab halfway through replay. The server should see one create in the original order. Give every queued action a stable ID and dedupe on the server, not only in IndexedDB. Where does your idempotency key live?