PayFlow
A financial transfer system built with three Go microservices that communicate exclusively through asynchronous messaging.
- Go
- PostgreSQL
- RabbitMQ
- Docker
Challenge
Coordinate a financial transfer across independently deployed services without relying on a shared database or synchronous coupling.
Approach
Model user, account, and transfer boundaries as Go services connected through RabbitMQ, with idempotency, choreographed Saga compensation, circuit breaking, and distributed tracing.
Outcome
A fault-aware transfer flow whose consistency decisions can be inspected through OpenTelemetry traces.
Architecture
Decisions and trade-offs
A choreographed Saga with no central coordinator
Each service reacts to events, which is simpler than running a separate orchestrator.
The transfer service has to keep the state of every transfer in flight.
Transfer never reads the account database; everything goes through RabbitMQ
The account service owns the balance data.
Transfer needs a timeout to notice a reply that never came and compensate.
The transfer reference is the idempotency key
A consumer that receives the same message twice, after a reconnect or a retry, produces the same result. Refunds use the same reference with a refund suffix.
Balances are stored as int64 cents
To avoid floating point errors in money.
