Back to work
case study 01

ARCA

An expense platform where the books can't go out of balance.

One-click demo roles on the sign-in screen.

Role
Solo. Design, backend, frontend, deploy
Type
B2B fintech web app
Stack
Angular 19, Spring Boot 4.1, PostgreSQL
Proof
Ledger tested on a real Postgres

The problem

Most expense tools are a form glued to a spreadsheet. Money moves, but nothing proves the books still balance. One wrong approval and finance loses a week hunting for a missing cent.

I wanted a system where an unbalanced ledger isn't a bug you catch later. It's impossible.

Three decisions that made it work

01

The database says no

Every approval posts its journal entry in the same transaction. A deferred constraint trigger checks that each entry sums to zero at commit, so even a buggy service can't write unbalanced books.

DEFERRABLE INITIALLY DEFERRED
02

Three roles, one truth

Employees submit with receipts. Managers approve or reject, and a rejection needs a reason. Admins get analytics, CSV export and the live trial balance. Checked on the API, guarded in Angular.

03

Receipts never go public

Receipt files only go out through signed links that expire after an hour. A forwarded link dies instead of exposing someone's dinner bill forever.

From the repobackend/src/main/resources/db/changelog/changes/0002-ledger-constraint.sql
SELECT COALESCE(SUM(amount), 0), COUNT(*)
  INTO v_sum, v_count
  FROM journal_lines
 WHERE entry_id = v_entry_id;
IF v_count > 0 AND v_sum <> 0 THEN
    RAISE EXCEPTION 'Journal entry % is unbalanced: lines sum to % (must be 0)', v_entry_id, v_sum
        USING ERRCODE = 'check_violation';
END IF;
...
CREATE CONSTRAINT TRIGGER trg_journal_lines_balanced
    AFTER INSERT OR UPDATE OR DELETE ON journal_lines
    DEFERRABLE INITIALLY DEFERRED
    FOR EACH ROW
    EXECUTE FUNCTION arca_check_entry_balanced();

Debits are stored as positive amounts and credits as negative ones, so a balanced entry sums to exactly zero. The check waits until commit, which lets both lines land first.

Designed to make money readable

Midnight#14181E
Credit teal#0F8F80
Debit coral#D75F3F
Copper#9C5A2A

Credit is teal. Debit is coral. You read the state of the books before you read a single number.

Figures sit in IBM Plex Mono with tabular numbers, so columns line up to the cent. On approval, a debit and a credit slide into balance.

Proof, not promises

Real PostgresLedger tests run on an embedded Postgres, not mocks
Sum to zeroA test proves an unbalanced entry is rejected at commit
End to endPlaywright runs the main flow in a real browser
CI on every pushBackend tests, frontend lint and build, browser tests

What I'd build next

  • Approval rules per team, with spending limits
  • Multi-currency entries with dated FX rates
  • Bank statement import with auto reconciliation

Want this level of rigor
on your product?

Let's work together Next project: Flowboard