vault
11 — Target Architecture
Target Architecture
This page describes a future state, not the shipped MVP. The current implementation is documented in 02-Architecture (Next.js App Router, Postgres ledger, mocked providers). This page describes the AWS-target architecture brief that will replace it during the refactor (target window: 10-Roadmap#Beta / 10-Roadmap#GA).
Why a target architecture exists
The MVP was optimised for getting end-to-end product flows shipped. The target architecture rebuilds the platform on AWS with explicit security boundaries, DR, regulated-grade access control, and a separated ledger/accounting layer (TRES).
Target principles
- Long-running containers, managed AWS around them. The application is a stateful Next.js standalone server plus a pg-boss worker — both long-lived Docker containers on EC2. Default to managed AWS for everything around the runtime (DNS, edge, database, secrets), not for the runtime itself.
- Private-by-default runtime. Application + data workloads stay in private subnets. Internet only via controlled entry/egress.
- Test mirrors Prod. Same topology for HA, networking, providers, CoSigner. See 12-Environments.
- Controlled provider dependency. Every provider has a defined purpose, integration boundary, failure role, and internal owner. See 05-External Providers.
- Transaction-centric platform model. One canonical Glossary#Transaction object connects product flow, provider event, status, and balance effect. See 02-Architecture for current shape.
- Internal ledger / accounting clarity. TRES is the target accounting layer; Fireblocks is custody/transactions. The two are documented and called separately.
- Auditability first. Every privileged or balance-affecting action lands in
audit_log. - Least privilege + role segregation. Admins are not equal; sensitive surfaces require explicit grants. See the privileged-actions list in 14-Operations and 07-Non-Functional.
- Documentation matches implementation. When the cutover happens, 02-Architecture is updated in lockstep with this page.
Stack (target)
| Layer | Component | Purpose |
|---|---|---|
| DNS | Route 53 | Authoritative DNS, health checks, weighted routing |
| Edge / CDN | CloudFront + AWS WAF + AWS Shield | Static delivery, WAF rules, DDoS, rate limit |
| Public entry | API Gateway | Public HTTP front door into AWS |
| Routing | internal ALB | Controlled routing into private application runtime |
| API runtime | EC2 (Auto Scaling Group, Multi-AZ) | Next.js standalone container serving user / merchant / admin traffic |
| Workers | EC2 (same ASG or a dedicated worker group) | pg-boss worker container: background jobs, exports, retries, provider integrations |
| Async coordination | pg-boss on Postgres | Durable queues, retries, scheduling — no separate broker |
| Custody runtime | EC2 + Nitro Enclave | Fireblocks CoSigner parent (isolated from the app instances) |
| Primary data | PostgreSQL (Multi-AZ in Test+Prod) | Application + transaction data |
| Rate limiting / short-lived state | Postgres (rate_limits) |
Rate-limit windows and login lockout — no separate cache tier |
| Static delivery | S3 (behind CloudFront) | Internal artifacts, exports, public assets |
| Custody / signing | Fireblocks (provider) | Wallet operations, sign + send |
| Ledger / accounting | TRES (provider) | Balance/accounting interpretation, reconciliation |
| KYC | Sumsub | Onboarding gates |
| AML / risk (sanctions) | Elliptic | Per-address risk score + sanctions screening |
| On/off ramp + card acquirer | Mercuryo | Buy/Sell iframe; card acquiring (PCI scope sits with Mercuryo) |
| Rate oracle | CEX.IO API | Spot rates for quotes and rate-freeze |
| Resend | Transactional mail (API-key scoped) | |
| Admin entry | AWS IAM Identity Center (SSO) + WAF + private subdomain | Identity-aware admin posture |
| Secrets / keys | Secrets Manager + KMS | Credentials, encryption-at-rest |
| Observability | CloudWatch + CloudTrail + GuardDuty + Security Hub (Prod) | Logs, metrics, threat detection |
Traffic flow
user/merchant traffic admin traffic
| |
Route 53 + CloudFront Route 53 + CloudFront
AWS WAF / Shield AWS WAF (admin ruleset)
| |
API Gateway admin entry path (separate subdomain)
IAM Identity Center (SSO + MFA)
\____________ ____________/
\/
internal ALB (private)
|
app containers on EC2 (ASG, Multi-AZ)
|
┌────────────────────────┴────────────────────────┐
| |
Postgres (RDS) worker containers on EC2
data + pg-boss queues + rate_limits |
CoSigner (EC2 + Nitro)
|
┌──────────────────┬──────────────────────────┴───────┐
Fireblocks TRES Elliptic / Sumsub / Mercuryo / CEX.IO
(controlled outbound, NAT)
- All public entry is filtered by CloudFront + AWS WAF + AWS Shield.
- Admin uses a separate subdomain + AWS IAM Identity Center (SSO with MFA).
- Database, workers, and CoSigner stay private — no direct internet ingress.
- Outbound to providers goes via NAT egress.
See 13-Network-Model for the security-group breakdown.
Why TRES (not just Postgres)
The MVP keeps the ledger inside Postgres (ledger_entries). That works for product velocity but blurs two responsibilities:
- Operational execution (Fireblocks moves coins) — happens fast, on the request path.
- Accounting interpretation (what does this mean for the books) — happens reconciliation-time, often retroactively.
TRES is introduced as a separate accounting/ledger layer so:
- Reconciliation is not a Postgres
SELECTontransactions, it's a TRES report. - Accounting changes (fee splits, internal transfers, corrections) don't pollute the operational
transactionstable. - Audit reviewers see one consistent accounting view across operations + admin.
The application keeps its own internal status enum and posts to TRES; TRES is not the source of truth for product behaviour, it is the source of truth for accounting interpretation.
Why CoSigner forces EC2 + Nitro Enclave
Fireblocks CoSigner is the signing-policy enforcement runtime. It must run on dedicated hosts with isolated execution; AWS Nitro Enclave is the supported topology. It stays on its own instances, separate from the app and worker containers, so signing material is never co-resident with application code.
CoSigner topology:
- One CoSigner parent EC2 instance per AZ in Test + Prod.
- Nitro Enclave isolates signing material from the parent OS.
- Locked-down security group (
SG-COSIGNERin 13-Network-Model). - Outbound only to Fireblocks; no public inbound.
How current → target maps
| Current (02-Architecture) | Target (this page) | Notes |
|---|---|---|
| Next.js App Router on a single EC2 host | Same containers across an ASG in Multi-AZ | The runtime does not change — only its redundancy and placement. |
Postgres ledger_entries |
Postgres + TRES (accounting layer on top) | Keeps Postgres as system-of-record; TRES gets the accounting interpretation. |
MockFireblocks |
Live Fireblocks + CoSigner on EC2 + Nitro | Cutover gated by 09-Open Questions#Custody. |
MockEmail → mock_emails |
Resend | 09-Open Questions#Email deliverability. |
| AWS ALB + regional WAF MVP | CloudFront + AWS WAF + AWS Shield in front of API Gateway; IAM Identity Center for admin | Adds DDoS + identity-aware admin entry while staying fully in AWS. |
✅ shipped — Postgres rate_limits |
Done ahead of this page. 08-Risks and Drawbacks#Security. | |
runJob fire-and-forget |
✅ shipped — pg-boss workers on Postgres | Done ahead of this page; survives restarts. The target only changes where the worker container runs. 09-Open Questions#Background queue. |
| Single deploy region | Multi-AZ + DR to secondary region | Test + Prod both. |
Out of scope for this page
- Specific resource sizing per environment — see 12-Environments.
- Security-group-level rules — see 13-Network-Model.
- Day-2 operations + runbook plan — see 14-Operations.
- Live-cutover migration plan — tracked under 10-Roadmap#Beta.
Drawbacks
- The cutover is large. A staged migration (data layer → CoSigner → workers → API surface) is the only realistic path.
- TRES is a new vendor dependency — see 09-Open Questions#TRES alignment.
Open Questions
- 09-Open Questions#Custody — Fireblocks vs alternatives.
- 09-Open Questions#Background queue — planned pg-boss orchestration details.
- 09-Open Questions#Multi-region — when to add a second region.
- 09-Open Questions#TRES alignment — TRES scope vs Postgres ledger boundary.
- 09-Open Questions#CoSigner topology — DEV CoSigner profile (sandbox vs production-like).
Cross-references
- Current architecture: 02-Architecture
- Environments: 12-Environments
- Network + security groups: 13-Network-Model
- Operations + runbooks: 14-Operations
- Glossary: Glossary