DEV Community

Cover image for SaathCare
saurabh gupta
saurabh gupta

Posted on

SaathCare

Building SaathCare: A Shared Elder-Care Ledger with an Append-Only Expense System

SaathCare is a project I built to solve a genuinely real problem: when a family shares caregiving duties for an aging parent — especially when siblings are spread across different cities — there's usually no single source of truth for who's doing what, or who's paid for what. WhatsApp threads and mental math don't scale.

Live app: https://saathcare-client.vercel.app
API: https://saathcare.onrender.com
Repo: https://github.com/saurabhg4356/saathcare

What it does

  • Duty rotation & real-time task board — tasks assigned on a rotation, with live updates via Socket.io when someone marks a task complete, and a scheduled job that flags missed tasks automatically.
  • Immutable expense ledger — every expense is append-only. Corrections happen via a new reversing entry, never an edit or delete — enforced at the Mongoose schema level, not just trusted to application code.
  • Settle-up algorithm — computes each member's net balance, then greedily matches the largest creditor with the largest debtor to produce the minimum practical set of transfers. Implemented from scratch rather than pulled from a library.

A few technical decisions worth sharing

The Outbox pattern for notifications. Early on, notification sending was called directly from controllers — meaning a slow email provider could add latency to (or fail) a task-completion request. Moving to an outbox table + separate worker decoupled that completely: the main request only ever writes a DB record, and a background process handles the actual send with its own retry/backoff logic.

Idempotency keys on financial writes. A double-tap on "Add Expense" during a flaky connection used to create duplicate ledger entries, silently breaking every downstream settlement calculation. Idempotency keys (client-generated, checked server-side with a TTL-indexed collection) made retries safe without needing complex client-side state tracking.

GDPR-style account deletion vs. ledger integrity. Since expense entries are shared data affecting other family members' balances, deleting a user's data outright on account deletion would corrupt everyone else's history. The resolution: anonymize the departing user's historical entries rather than cascade-deleting them, preserving the ledger's integrity for the rest of the family.

Stack & production setup

MERN (MongoDB, Express, React, Node.js) + Socket.io for real-time events, JWT with refresh-token rotation for auth, Zod for validation, Helmet + rate limiting for baseline hardening. Deployed on Vercel (frontend) and Render (backend), with MongoDB Atlas, GitHub Actions CI/CD, and live /health and /ready probes. 57 automated tests across 16 suites (Vitest + Supertest).

What's next

Still on the roadmap: recurring task auto-generation, receipt attachments via S3, and a Redis-backed Socket.io adapter for horizontal scaling.

Would genuinely welcome feedback on the ledger design or the settle-up algorithm from anyone who's built similar systems — code's fully open at the repo link above.

webdev #node #mongodb #react #showdev``

Top comments (0)