Payout Engine
"Manual payouts turned into a routing engine — 40+ currency-method directions, delivered without losing a single callback."
- 40+
- 0
- 24/7
An exchange where every payout passed through a human — cards, IBAN, Wise, PayPal, Revolut, Interac, Idram, UZCARD, Humo. Rebuilt as a routing layer with durable delivery, so nothing depends on someone being awake.
Backend and integrations — payout services, exchange-side plugin, operator tooling, deployment.
Problem
Delivery was best-effort in the literal sense: one attempt out, one attempt back, errors logged and forgotten. A restart mid-payout left the money sent and the order stuck forever — and every new currency meant code changes in three places.
Approach
- 01Modelled directions as data — currency plus method maps to a route, so a new one is a table row, not a deploy.
- 02Made delivery durable: the result is written before the callback and cleared only on acknowledgement, with a background drain re-sending the rest.
- 03Retried only what time can fix — network errors, 5xx, expired auth — and made the rule a unit test so it cannot drift.
- 04Added a scheduled resubmit scan on the exchange side; the receiver deduplicates by UUID, so a repeat POST is simply a retry.
- 05Moved operator work into Telegram, instead of a dashboard nobody kept open.
- 06Moved the shipped demo secret out of the code into CI-injected environment values.
Outcome
- →Payout results survive restarts, deploys and network failures — the queue drains and delivers.
- →40+ currency-method directions live, from GBP and CAD to UZS, TJS, GEL, AMD and NGN.
- →Requests can no longer be lost between exchange and payout service: dedupe by UUID makes re-posting safe.
- →Deposits that used to be entered by hand are now processed automatically.
- →Operator workflow runs in Telegram, with the admin panel as an audit surface rather than a bottleneck.
Business Impact
The payout desk stopped being a person: requests route themselves and confirm back unsupervised, including through restarts that used to cost a stuck order. Adding a market is now configuration — which is why the direction count passed forty.
Under the hood
Payout Services
- Rust · durable callback queue
- SQL migrations · pending-result table
- Retry policy unit-tested
- Telegram operator bots
Exchange Integration
- Laravel plugin · scheduled resubmit scan
- UUID deduplication · 409 as retry signal
- Provider parsers (Node)
- Secrets via CI, none in code
Platform Services
- NestJS · Prisma · Telegraf
- Nuxt exchanger storefront · i18n · PWA
- Java · Spring P2P service
- PDF generation service (NestJS)
Infra & Ops
- Docker Compose per service
- GitHub Actions · secrets to env
- Self-check scripts on host
- Structured logs for delivery tracing
Have a system that needs building?
Payments, integrations, mobile, data pipelines — if it has to run unattended and be correct, that is the work I take. From architecture through launch, and I stay to keep it running.