Show HN: 66 Lines of Markdown compiled to a 7k lines Postgres back end

imrozim1 pts0 comments

Forgx — a compiler for backends

⚒">

Forgx

Auth, tenant isolation, migrations, money that survives a race —<br>three months and $9,000–12,000 before your first feature exists.

Describe your backend. Get a real one.

A multi-tenant Node and Postgres API, compiled from a markdown spec and<br>run against a live database before it reaches you .

You write this

### order<br>Status: pending, paid, shipped,<br>delivered, cancelled<br>Workflow: pending → paid → shipped<br>Business Rules:<br>- When an order is cancelled after<br>payment, refund the amount to the<br>customer's wallet as store credit.

You get this

orders table, with the status list as a CHECK constraint

PATCH /transition — illegal moves rejected, not logged

An RLS policy Postgres enforces, not your WHERE clause

Idempotency-Key on create — a retry is a replay

A wallet , its ledger, and the refund path to carry that last rule

66 lines of markdown → 7,722 lines · 85 routes ·<br>26 tables · 21 RLS policies · 326/332 assertions passing

Three entities in, 26 tables out. The same run wires JWT auth,<br>billing, Stripe , webhooks, cron, rate limiting and sockets — whichever your<br>rules ask for.

Not an illustration — that is quickkart's actual spec.<br>The whole file ships in the repo as<br>SPEC.md,<br>next to the code it produced, so you can count the ratio yourself.

Ten minutes to compile. One to two days to deliver — the difference<br>is me running it against a real Postgres and fixing what falls out before you see it.

Tell me what you're building →<br>Read the generated code

The part of the project nobody quotes for

Before a single feature exists, this has to be built. Every backend needs it,<br>nobody demos it, and it is where the schedule goes.

66 to 98 developer-days. Three to five months for<br>one person; four to seven weeks for a team of three. A quote for this work usually reads<br>$9,000–12,000 — and three months.

The eight layers, and what each costs

LayerDays

Auth — signup, login, refresh, hashing, token rotation6–8<br>Multi-tenancy, row-level security and roles — done properly10–15<br>CRUD with validation, pagination, filters, soft delete6–8<br>Money — transactions, row locks, idempotency, concurrency6–10<br>Double-entry ledger, multi-currency, approvals11–17<br>State machines, migrations, audit log, cron9–13<br>Typed errors, rate limiting, headers, health probes, Docker6–9<br>The test suite that proves any of it works12–18

The three rows in bold are the ones that get cut first when the deadline<br>moves. Every row is generated except the last — the compiler does not write your<br>test suite. What the one to two days buys instead is your backend run against a live<br>Postgres by me, with whatever surfaces fixed before you get it.

It builds production backends, not scaffolding

In every backend, whether the spec asks or not:

JWT auth with rotating refresh tokens · row-level security<br>Postgres enforces · role checks on every route and as a DB constraint ·<br>transactions with row locks · idempotency keys · versioned migrations ·<br>audit log · cron scheduler · rate limiting · Helmet · CORS · Docker

What each of those actually means

Tenant isolation

Enforced by Postgres, not by your WHERE clause — and<br>bound transaction-locally, so one tenant's context cannot leak into another's query.<br>Measured below.

Authentication

Signup, login, refresh, logout. PBKDF2 at 310,000 iterations, httpOnly<br>SameSite-strict cookies, rotating refresh tokens revoked on logout.

Roles and input

Roles enforced twice — on every route and as a CHECK<br>constraint in the database. Per-entity validators with an unknown-field guard, so a<br>client cannot set tenant_id, role or a balance from the body.<br>Every query parameterised.

Money safety

Balance writes run in a transaction with row locks, and idempotency keys<br>make a retried request a replay rather than a double charge. Measured below.

Wired end-to-end

A dead wire is caught at compile time. Every import, job and<br>service reference must resolve before the backend ships — ledgerpro's last run:<br>63 files, 122 references, 0 dangling .

Ready to deploy

docker compose up and it serves traffic. Multi-stage<br>Dockerfile as non-root with a HEALTHCHECK, compose,<br>.env.example, checksum-tracked migrations, /health and<br>/ready, audit log, cron, rate limiting, Helmet, CORS, licence and docs.

Your own code

Custom logic lives in hook files the compiler writes once and never<br>overwrites. Change the spec, re-run, and your code is still there.

The specification decides what gets built

Not one template with the nouns replaced. Five specs,<br>five genuinely different backends.

Five specs — e-commerce, fintech, productivity, healthcare, mobility — compiled to<br>348 routes · 92 tables · 67 RLS policies · 36,765 lines , from 492 lines of markdown.<br>Two of the five are verified end to end; the other three boot but have not had the same<br>sweep, and the limits section below says so. A boilerplate is one codebase everyone<br>receives and then deletes from. Compare the two published backends: they share the<br>platform and almost...

postgres three lines before backend spec

Related Articles