binary-sync-migrate
Convert an existing JSON polling or sync endpoint that returns live positions (vehicles, couriers, devices, riders) to gaza-geo-sync's binary frame while keeping JSON as the fallback. Use when the use
SKILL.md.claude/skills/binary-sync-migrate/SKILL.md
GitHubMigrate a JSON positions sync to gaza-geo-sync
Full guide: docs/MIGRATION.md in https://github.com/AQaddora/gaza-geo-sync. Work in this order;
each step ships on its own and nothing breaks between steps.
0. Find and measure first
- Locate the endpoint(s) and every client that calls them (
grep -rn "positions\|location\|/sync"). - Record today's numbers with the
binary-sync-verifyskill (bytes per refresh gzipped, refresh interval, upload interval). No baseline → no claim. - Write down the exact JSON shape clients parse. That shape is the contract for the fallback and for the offline cache.
1. Cheap wins that need no binary
- Round coordinates to 5 decimals (
codec.round) in the JSON too: ~30% less gzipped. - Standing-still throttle on uploads (
worthSending): fewer requests, which matters more than bytes for small uploads (HTTP headers are ~400–800 B each).
2. Give each object a stable small number
- Additive migration:
seq SERIAL UNIQUE(or equivalent). Backfill happens automatically. - Expose
nin the JSON form of the object list so clients can learn it.
3. Server: negotiate
- Wrap the handler with
positionsReply(seetemplates/nextjs-route.ts/templates/express-server.ts). JSON whenAcceptlacksapplication/octet-stream— identical to before. - Split the response: everything except positions goes in the frame's JSON part (
extra), positions in binary. Includeindexon full syncs. - Add
Vary: Accept(done by the helper) so no cache mixes the two forms.
4. Client: decode on arrival
- Replace
await res.json()withfetchPositions(...). It returns the old JSON shape. - Store records exactly as before; additionally store the
[n, id]index. - Bump the client's local schema/cache version once so existing installs do one full sync (they need the numbers).
5. Uploads
- Server accepts both bodies (
readPointBody), replies 204 to binary. - Client:
createPointSender(binary first, JSON after a 400/415).
6. Prove it
- Run the project's tests + add round-trip tests for the endpoint (both Accept values).
- Use
binary-sync-verifyto measure after; report before/after honestly, including where it did not help.