Evidence-based architecture overview of Corebanq, the core banking platform behind regulated EU PI / EMI institutions. Compiled from source-code analysis of the live system. The page is the single point of reference for technical buyers, integration engineers, and procurement teams evaluating the platform.
Source-of-truth
Live Corebanq monorepo — Go API + listener service + multi-tenant SPA
The platform is a Go-on-Postgres core banking system with a multi-tenant React SPA in front and an event-driven listener service behind. The numbers below are evidence-based from the live source tree at the cut-off date — every component referenced in the sections that follow is indexed under one of them.
45+
API modules · Go
3
Microservices · API · Listener · Frontend
14
Internal Go connectors
17
External integrations
8
Common cross-cutting packages
5
Shared frontend libraries
/0.2 Stack signature
Eight runtime anchors
The technology stack is deliberately narrow. One language for all backend services (Go), one database for all authoritative state (PostgreSQL), one orchestrator (Kubernetes on EKS), one cloud (AWS). Every component below is in production use; nothing is research-stage.
Go 1.25
API + connectors + listener
TypeScript / React 19
Multi-tenant white-label SPA
PostgreSQL
Authoritative ledger + outbox
Redis
Cache · rate limits · pub/sub
Kubernetes / EKS
Production runtime
AWS
Managed services + secrets
RabbitMQ
Outbox relay · event queue
DSL Engine
Banking-product workflow rules
/0.3 Surfaces & gateway
Customer-side, operator-side, and the edge between them
Two SPAs (customer + admin) sit in front of one API gateway. The gateway authenticates, authorises, rate-limits, and tenant-routes every request before any module sees it. There is exactly one surface for the platform and exactly one gateway — multi-tenant routing is internal, never per-tenant deployment.
Client tier
web-app
Customer portal
Multi-tenant white-label SPA. Per-tenant theming, locale and routing resolved at boot. SSE-driven notifications.
Self-hosted UI documentation with theme variants and MSW-mocked API responses.
UI componentsMSW mocksTheme variants
Gateway tier
HTTP/HTTPS server
Edge router
Go · Chi Router v5 on :8080 / :8443. Every request enters here; authentication, rate limiting and tenant isolation are enforced before any module sees it.
The Go API is structured as functional clusters — each cluster a directory under corebanq.api/ with its own subpackages, GORM models, and DSL hooks where applicable. The double-entry ledger sits at the centre; every other cluster integrates with it via the outbox pattern (see /0.8) so no module owns its own settlement.
Custom interpreterGL booking from rulesTransaction state machineProduct-version audit
DSL example — outward wire transfer rule
# OWT — outward wire transfer
rule "OWT" {
when case {
tariff { type: "exchange" }
gl-batch { txn = id
book ledger = "22011" op = debit
}
call { interface: "kyt_service" }
route { event: "complete" }
}
}
Banking products are first-class artefacts compiled and versioned by the rule engine. Every rule is auditable — the same DSL that runs the platform is also the audit trail of what ran.
/0.5 Internal connectors
Fourteen single-purpose adapters
Every external runtime concern (a database, a queue, an SMS gateway, an LLM endpoint) sits behind a single-purpose adapter under corebanq.api/connectors/. Modules consume adapters by interface; the adapter is the only place that knows the wire format. Adapter-swapping is a configuration change, not a refactor.
db
PostgreSQL via GORM + pgx/v5
Connection poolgorm_loggerMigrations
ram
Redis · rate limits · cache
In-memoryRedis driverRate counter
email
Mailjet · AWS SES · SMTP
TemplatesWebhookDB overlay
sms
Twilio SDK
OTP SMSTemplatesi18n
queue
RabbitMQ · AWS SQS · Local
amqp091-goSQSLocalQueue
storage
MinIO · AWS S3
minio-go/v7aws-sdk-v2/s3File mgmt
kyc
Identity verification · sanctions
IDV providerSanctions DBPolling
kyt
Fiat + crypto monitoring
Fiat screeningCrypto KYTTRX adapter
crp
Crypto payment rails
gRPC clientREST clientMerchant mgmt
lm
LLM — Bedrock · Ollama
AWS BedrockOllamaChat assist
ocr
GoTesseract microservice
Document OCRHTTP service:8081
im
Telegram · Console driver
Telegram botTemplatesPluggable
totp
TOTP 2FA (pquerna/otp)
QR generationBarcodeAudit log
push
Push notifications
FirebaseAPNs
/0.6 Storage & runtime
Eight services on the production runtime
Production runs on Kubernetes (EKS, eu-central-2). Development runs on Docker Compose with the same service list, minus AWS-managed substitutions. PostgreSQL is the source of truth for every record; Redis carries ephemeral state only; RabbitMQ is the reliable-messaging bus that connects the API to the listener service.
Go · HTTP :8090, metrics :8091, health :8092, pprof :8093
TOTP workers, webhook delivery, queue relay
/0.7 Cloud & external
AWS-managed core, narrow third-party perimeter
The cloud surface is small and named — eight AWS services plus a third-party integration list grouped by control category. Every external integration sits behind one of the internal connectors in /0.5 — there is no direct external call from a module.
Instant messaging for ops alerts / compliance, telegram-bot-api/v5.
CI / CD
Self-hosted GitLab
Stage runner on EKS, ECR push.
Quality
SonarQube
Code quality analysis, sonar-project.properties present in all services.
/0.8 Transaction lifecycle
Outward wire transfer — DSL-driven state machine
Transactions are not implemented as ad-hoc Go code. They are declared as DSL rules — OWT_1.0.0.dsl, IWT_1.0.0.dsl, OWN_1.0.0.dsl — interpreted by the rule engine. The diagram below is the actual state machine for an outward wire, not a stylised summary. Every node is a step the engine takes; every transition is auditable.
Side effects never block the API. Each module writes the side-effect intent into a Postgres outbox row in the same transaction as the state change. A poller fans the outbox into RabbitMQ; corebanq.listener consumes from RabbitMQ and delivers webhooks, runs TOTP workflows, and persists Redis state. If the listener stalls, the API does not.
The Postgres schema is normalised around twelve principal entity groups. GORM models map 1:1 to the API response shapes; there is no service-side aggregation layer that could drift from the database.
The Finray marketing site loads no analytics or marketing cookies
today. We record your decision below in your browser's local
storage so we can honour it if we ever add a privacy-respecting
analytics layer. Read the
Cookie Policy for details.