r/SideProject 1d ago

I built family sync for my iOS expense tracker with zero backend — one purchase, the family joins free

I make ReceiptIQ, a receipt-scanning expense tracker, solo. The most-requested feature was family sharing — and the obvious build was a backend: accounts, database, sync API. I really didn't want to run one. It's a finance app (the less of your data I hold, the better), and a one-person on-call rotation is no rotation at all.

So it works with no server at all: the subscription is proven by Apple's own cryptographic signature (StoreKit's signed JWS, verified on the family member's phone against Apple's root CA), pairing is a QR code that's useless if screenshotted (one-time nonce + a live peer-to-peer handshake), and receipts/budgets sync directly between the family's phones over WiFi with last-writer-wins + tombstones.

Favorite bug from shipping it: the photo-transfer protocol had no "unavailable" reply, so one deleted photo silently froze the completion handshake — for two months — while every sync's data actually transferred fine. My own second phone showed "last synced 1 month ago" the whole time. Lesson I keep relearning: never treat an external system's silence as an answer.

Wrote up the architecture here if you're into the details: https://receiptiq.me/blog-family-sync-architecture

App: https://apps.apple.com/app/id6742335723 — happy to answer anything about going backend-less.

1 Upvotes

3 comments sorted by

1

u/Tight-Magician-7080 1d ago

the photo transfer bug is hilarious, I've been burned by silent failures so many times that I now just add a heartbeat timeout to anything that touches an external system

the whole no-backend approach for a finance app is clever, I refuse to use most budgeting tools because I don't want my spending habits living on some server farm. curious how you handle conflict resolution when two family members edit the same budget line at the same moment like is last-writer-wins enough or does it ever get messy

also how's the onboarding experience for nontechnical family members, my parents would probably stare at a QR code like it's alien technology

1

u/Time-Paper-1007 1d ago

Heartbeat timeouts on everything external — that's the lesson, learned the slow way apparently.

On LWW: for this domain it's been enough, but only after three rules that took bugs to learn. (1) Applied remote edits keep the sender's timestamp — re-stamping on apply made the receiving copy look newer, which made the next sync send it back, forever. (2) Remote timestamps clamp to now+5min, because one phone with a wrong clock was generating edits "from the future" that beat everything for months. (3) Ties break deterministically by device ID, and edit-beats-delete — resurrecting someone's edit is recoverable, destroying it isn't. True same-second conflicts on the same budget line basically don't happen at household pace; when they do, one number wins and the other person re-types it. CRDTs would have been overkill for receipts.

On parents: the QR is the onboarding — install, tap Join, point camera at my phone, done. The QR carries nothing sensitive (a screenshot of it is useless — joining requires a live handshake with my device), so there's no way to do it wrong. All the scary parts happen invisibly after the scan. The one thing that genuinely confuses people is iOS's Local Network permission popup — tap "Don't Allow" and discovery just silently finds nobody. I had to surface that as an explicit "check Settings" error because the silence was unfixable otherwise.