Jump to a section
Overview
Fluxa is a real-time game in which players predict live BTC price action, either with a demo balance or with a real crypto balance funded through a payment provider. The backend is a TypeScript modular monolith on Fastify with PostgreSQL, Redis, BullMQ queues and WebSockets; the frontend is Nuxt.
I own the product and built it with one other engineer, who wrote more of the code overall: about a third of the commits are mine. Mine are concentrated in the game and payment code, the hardening pass described below, the market-data pipeline and all of the production infrastructure.
Fluxa in production
Images of the real product; the note below says where and how they were captured.


Hardening the money path
In February 2026 I reviewed the backend's money paths and scale-out paths and fixed each finding in its own commit, 17 in all:
| Problem | Fix |
|---|---|
| Some balance changes (deposit confirmation, payment confirmation, admin top-ups) bypassed the ledger | Every balance change now goes through one function that writes the ledger entry in the same transaction |
| Two concurrent payment or deposit confirmations could both credit the balance | Confirmation is a compare-and-set update; only the transaction that actually changes the status credits the balance |
| Settlement updated in-memory state before the database commit | The database commits first; caches are updated only after it succeeds |
| N+1 queries in trade reconciliation and payment-method discovery | One batched query; provider minimums cached with a short TTL |
| Calls to the payment provider had no timeout | Each call has a timeout and a distinct, logged timeout error |
| Unbounded history reads and in-memory maps | Pagination with a cap; periodic sweeps and size limits on in-memory maps |
| Missing indexes for the hottest queries | Composite indexes that match the real query shapes |
| Games kept accepting bets while Redis was down | Games fail closed: new actions are refused until Redis is back |
| Per-instance state broke with more than one instance | Settlement workers load state from Redis; one connection per user is enforced across instances |
The confirmation pattern, simplified:
const changed = await tx.payment.updateMany({
where: { id, status: { not: "CONFIRMED" } },
data: { status: "CONFIRMED", confirmedAt: new Date() },
});
if (changed.count === 0) return alreadyConfirmed(); // someone else won: credit nothing
await creditWithLedger(tx, userId, amount, "DEPOSIT", id); // exactly once, with its ledger entry
Market-data pipeline
In September 2026 I built the pipeline that supplies historical candles for a chart-based game mode. An admin chooses an instrument, timeframe and date range; the request becomes a BullMQ job that downloads Dukascopy data month by month.
- Idempotent inserts. Rows are inserted in batches with duplicates skipped on their natural key, so any retry or repeated download leaves the data unchanged.
- Resumable. A retried job continues from its last completed month instead of starting over.
- Cancellable. Cancelling a running job sets a flag the worker checks before each month.
- Isolated. Decompressing the source files is CPU-heavy, so the worker runs in its own process from the same image and cannot delay the live price stream.
The work was written with an AI coding agent from a specification and plan I approved, and its unit tests were written to fail before each fix. The other engineer later moved the candle table to a compressed TimescaleDB hypertable.
Production
Fluxa runs on Docker Swarm behind Cloudflare: nginx with TLS and rate limits, the API, a worker process, PostgreSQL and Redis, with credentials as Swarm secrets. GitHub Actions workflows deploy from a self-hosted runner on the target host after checking that Swarm and the required secrets are present.
Limitations
- Deploys are started by hand and do not run the test suites first.
- I did not load-test the hardening changes; the repository's load scripts are the other engineer's.
- No usage or revenue figures are published.
Evidence index
Every claim this case study relies on, rendered from the evidence manifests.
Hardening the money paths of a live game
Reviewed and fixed the money and scale-out paths of Fluxa's TypeScript (Fastify) backend in 17 commits: every balance change writes a ledger entry in the same transaction, deposit and payment confirmation use a compare-and-set so concurrent confirms cannot double-credit, N+1 queries, missing timeouts, unbounded reads and missing indexes are fixed, and games fail closed when Redis is unavailable.
Historical market-data pipeline
Built Fluxa's historical candle pipeline: a BullMQ job queue that downloads Dukascopy data in monthly chunks, inserts idempotently, resumes from its last checkpoint after a retry, can be cancelled, and runs in a separate worker process so it never blocks the live price stream.
Fluxa production deployment
Set up Fluxa's production on Docker Swarm: nginx with TLS and rate limits, Swarm secrets, and GitHub Actions workflows that deploy from a self-hosted runner on the target host after checking that Swarm and the required secrets exist.