Behind the product

The interface is simple.
The numbers have rules.

A full-stack engineering case study in financial precision, auditable edits, database concurrency, and honest market-data states.

Browser

Next.js + React

Accessible forms, filter controls, request-generation guards, and an isolated sample-data preview.

API

Java 25 + Spring Boot

JWT authorization → controller → service. Validate, lock, revise, replay, and commit.

Data

PostgreSQL + Flyway

Ledger revisions, derived holdings, schema constraints, UTC execution times, and quality-labelled snapshots.

Decisions worth discussing

01

A ledger, not a mutable balance

Creates, edits, and deletes replay active trade revisions into a holdings read model. Replacing an entry preserves the previous revision; invalid historical sells roll back the entire change.

02

Execution time ≠ record time

An optional execution timestamp is stored in UTC, separately from the original audit timestamp. Replay orders by execution time, then stable ledger sequence. Backdating is supported; future trades and historical oversells are rejected.

03

Precision before presentation

Quantity uses eight decimal places; prices and average costs use twelve, with twenty-place cost basis and realised-profit allocation. USD totals round to cents at their defined output boundaries—not before multiplying a small unit price.

04

Concurrency has an owner

A database row lock serializes each user's writes. Active-revision and holding constraints protect invariants; concurrent users can safely introduce the same asset into the shared catalog.

05

Market uncertainty stays visible

Quotes expire, cached fallback has a maximum age, and upstream requests have timeouts and backoff. Stale, missing, or uncertified observations are labelled rather than shown as trustworthy zero-value history.

06

Queries stay on the server

Owner-scoped symbol/type/date filters and allowlisted sorts run in PostgreSQL before pagination. CSV uses one bounded, repeatable-read snapshot so concurrent edits cannot shift rows between export pages.

A correction without rewriting the past

  1. 1. Record: buy 2 units at $10, then sell 1 at $20. Remaining cost is $10; realised profit is $10.
  2. 2. Correct: replace the original buy with a $12 entry. Keep its previous revision, replay the active trades, and obtain $12 remaining cost and $8 realised profit.
  3. 3. Protect: move that buy after the sell. The replay would oversell, so the entire edit rolls back. The valid ledger remains unchanged.

Affected snapshots are invalidated, not invented retroactively. New observations resume after the committed change.

Evidence, not just a diagram

  • Real PostgreSQL migration, concurrency, rollback, precision, export-boundary, and restore tests.
  • HTTP checks for ownership isolation, backdated execution, invalid filters, and audit-preserving revisions.
  • Browser checks for registration → trade → edit → filtered CSV → delete, plus populated mobile widths.
  • Automated dependency and container advisory gates alongside build, unit, integration, and browser checks.

Deliberate limits

This is a personal tracker, not an exchange or tax engine. History is point-in-time valuation, not a cash-flow-adjusted investment return. Ledger replay remains linear; history/export is capped at 10,000 matching rows.

The public demos are deterministic frontend fixtures, not seeded customer accounts or proof of a live backend. Account verification/recovery, production restoration, trusted proxies, and deployment still have explicit launch gates.