🔄 LedgrSync

Cross-entity ledger reconciliation on Aurora DSQL

Ingest transactions from each entity and automatically surface what doesn't match — across entities and AWS regions — on a distributed, multi-Region SQL database that never sleeps.

CI Next.js React Aurora DSQL Prisma Tests

🚀 Live Demo · 📊 Dashboard · 🐙 GitHub

💡 Inspiration

Every company that operates across regions or entities eventually hits the same wall: two ledgers that should agree, but don't. A subsidiary in the US books a transfer; the EU entity records it a cent off, or a day late, or never at all. Finding that one broken row means exporting spreadsheets, eyeballing columns, and praying.

We wanted to see if Aurora DSQL — AWS's new serverless, strongly-consistent, active-active multi-Region database — could turn that nightmare into a single API call. The pitch was simple: one source of truth that spans regions, and an engine that tells you exactly what doesn't match.

⚙️ What it does

LedgrSync ingests transactions for multiple entities and reconciles their ledgers automatically. Transactions that should appear on both sides share a referenceId; the engine pairs them and classifies every divergence:

Type Meaning
🟡 amount_mismatch Same reference, different amount
🔵 status_mismatch Same reference, divergent status (e.g. posted vs pending)
🟠 missing_in_b Present in A, absent in B
🔴 missing_in_a Present in B, absent in A

Formally, reconciling ledgers $A$ and $B$ checks the union of their references and flags everything that disagrees:

$$ \text{checked} = \bigl|\,R_A \cup R_B\,\bigr| \qquad D = {\, r \in R_A \cup R_B \;:\; t_A(r) \neq t_B(r) \,} $$

You get a live dashboard: add/delete entities and transactions, run a reconciliation between any two entities, and watch discrepancies — plus a real-time concurrency-conflict log — appear instantly.

🚀 Try it live: ledgrsync.vercel.app → click "Try the live demo" (no signup).

🏗️ How we built it

  • Frontend & API — Next.js 16 (App Router) + React 19, deployed on Vercel. A marketing landing page at /, an auth-gated dashboard at /dashboard.
  • Database — Aurora DSQL via Prisma 7 with the pg driver adapter. We authenticate with short-lived IAM tokens (@aws-sdk/dsql-signer) refreshed per connection — no static DB password anywhere.
  • Two reconciliation engines, sharing one pure comparison core:
    • a streaming engine that indexes the smaller ledger and paginates the larger (memory bound by the smaller side), and
    • a SQL engine that runs a FULL OUTER JOIN inside DSQL (memory bound by the number of discrepancies — for when both ledgers are huge).
  • Concurrency — DSQL uses optimistic concurrency, so we wrap writes in withOCCRetry, which retries serialization conflicts (40001) with exponential backoff and logs each one for observability.
  • Multi-Region — two peer clusters (us-east-1 + us-east-2) sharing data, with a witness Region (us-west-2) for quorum, provisioned end-to-end with the AWS CLI.
  • Qualityzod validation, a self-contained HMAC + scrypt auth gate, 56 Vitest unit tests, and GitHub Actions CI on every push.
# the whole product in one call
curl -X POST /api/reconcile \
  -d '{ "entityAId": "acme-us", "entityBId": "acme-eu", "engine": "sql" }'
# → 201 { "totalChecked": 5, "discrepancies": [ ... ] }

🧗 Challenges we ran into

  • next-auth wouldn't run. v4 is incompatible with React 19 / Next 16. Rather than ship an unsupported dependency, we built a small, fully-tested HMAC session cookie + scrypt auth gate ourselves.
  • The database was unreachable in dev. DSQL endpoints resolve to IPv6 first, and our WSL2 environment had no IPv6 egress — every connection timed out. We diagnosed it down to the socket and forced IPv4 + a correct TLS servername so SNI still worked.
  • You can't upgrade a cluster to multi-Region. AWS rejected converting our existing single-Region cluster in place ("Multi-Region properties were provided for a single-Region cluster"). We learned the real flow: create a fresh pair with witnessRegion set, then peer them — and migrated cleanly.
  • Trusting the distribution. We didn't want to assume replication worked, so we seeded data in us-east-1 and read it straight back from the us-east-2 endpoint to prove active-active consistency.
  • Serverless + a connection pool. Making Prisma, a pg pool, and per-connection IAM tokens behave on Vercel's serverless runtime took careful, build-aware connection handling.

🏆 Accomplishments that we're proud of

  • A genuinely live, multi-Region deployment — not a mock. Data written in one AWS Region is instantly readable in another, verified end-to-end.
  • Two reconciliation engines that provably return identical results, so you can trade memory for scale without changing behavior.
  • Zero static database credentials — everything runs on rotating IAM tokens with least-privilege (dsql:DbConnectAdmin only).
  • Hardened from hackathon-grade to production-grade: auth, validation, centralized error handling, 56 passing tests, CI, and a polished design system.
  • Shipped a real public product with a landing page, one-click demo, and full CRUD — anyone can try it right now.

📚 What we learned

  • Aurora DSQL changes how you design. No foreign keys (relations enforced in-app), optimistic concurrency instead of locks, and multi-Region that's active-active by default — it rewards rethinking assumptions from row one.
  • IAM-based DB auth is a superpower. Short-lived tokens remove an entire class of secret-management risk.
  • The "boring" layers decide whether you ship. DNS/IPv6, TLS SNI, connection pooling, and cold-start behavior were where the real time went — and where a demo becomes a product.
  • Honest verification beats optimism. Proving replication and engine-equivalence with live tests caught what assumptions would have hidden.

🔭 What's next for LedgrSync

  • Scheduled & streaming reconciliation — continuous, not just on-demand.
  • Multi-user & RBAC via Auth.js v5, with audit trails per reviewer.
  • Richer discrepancy resolution — assign, comment, and resolve, with exports (CSV/JSON) and webhooks.
  • Tolerance rules — currency-aware rounding and configurable thresholds (e.g., flag only when $|\Delta| > \epsilon$).
  • 3+ region topologies and per-Region latency routing.
  • Connect real sources — bank/ERP/payment-processor adapters so ledgers flow in automatically.

Built With

Share this project:

Updates