Leave Tracker
Mini HRIS where employees file leave and managers approve it, built for correctness: a Go API with idempotent requests, row-level locking and an audit trail, a Next.js backend-for-frontend that keeps the JWT out of the browser, concurrency tests, and CI.
The problem
Leave tracking looks simple until two managers click approve at the same time, a flaky network retries a request, or a balance gets deducted twice. Most small HR tools ignore these races and leak tokens to the browser.
The solution
A Go API that treats every write as a transaction: idempotency keys de-duplicate retries, row locks serialize approvals, and an events table records who did what. A Next.js backend-for-frontend holds the session in an httpOnly cookie and proxies an allow-list of endpoints. Concurrency tests prove the guarantees, and CI checks them on every push.
Screenshots
Architecture
- FrontendNext.js 16React 19shadcn/uiTanStack QueryZod
- BFFNext.js route handlershttpOnly session cookie
- APIGochiJWTrate limiting
- DataPostgreSQLpgxgolang-migrate
- QualityGo race testsVitestPlaywrightGitHub Actionsgovulncheck
- HostingDockerRailway
Highlights
- Backend-for-frontend: the JWT lives in an httpOnly cookie read only by the Next.js server; the browser never sees it and the Go API needs no CORS.
- Allow-listed proxy route with an Origin check on top of SameSite=Lax, and revocable server-side sessions so logout really ends the token.
- Idempotency keys on leave creation: ten concurrent retries create exactly one request and one event.
- Approvals lock rows with FOR NO KEY UPDATE, so balances are never double-deducted and concurrent cross-approvals produce zero deadlocks.
- Every change (created, cancelled, approved, rejected) is written to an events table in the same transaction.
- Keyset pagination, weekday-only day counting, overlap detection and per-IP rate limiting.
- CI runs go vet, govulncheck, race-detector unit and integration tests, npm audit, lint, typecheck and tests.
- Deployed on Railway with Docker, private networking and pre-deploy migrations.



