A single Go binary. 6 real-time exchange feeds. 150 prewarmed assets. Table-driven everything. v8 UDP engine. 24-counter telemetry. One person runs it all.
The Trinity Beast is a single Go binary that serves real-time cryptocurrency prices from 6 exchanges, reports usage analytics in 4 formats, manages subscriptions via Stripe, processes partner applications, and publishes 30+ CloudWatch metrics — all from one main.go controlled by a SERVER_TYPE environment variable.
Adding a new exchange to The Trinity Beast requires zero code changes. The Exchange Manager reads its configuration from two Aurora tables and launches WebSocket connections dynamically.
Add Exchange #7: Insert one row into exchange_feeds (endpoint, subscribe template, JSON paths, ping interval) and 24 rows into exchange_asset_map (asset-to-symbol translations). Restart the container. The new exchange is live — receiving real-time trades, caching prices, and appearing in the demo dropdown. No Go code touched.
graph TD
TBCC[TBCC Exchange Manager] -->|"CRUD API"| EF[(exchange_feeds
19 columns)]
TBCC -->|"CRUD API"| EAM[(exchange_asset_map
150 rows)]
EF -->|"on startup"| EM[Exchange Manager
Go Engine]
EAM -->|"symbol lookup"| EM
EM -->|"launches"| WS1[Coinbase WS]
EM -->|"launches"| WS2[Gemini WS]
EM -->|"launches"| WS3[Kraken WS]
EM -->|"launches"| WS4[Gate.io WS]
EM -->|"launches"| WS5[Crypto.com WS]
EM -->|"launches"| WS6[OKX WS]
WS1 -->|"prices"| PC[sync.Map
Price Cache]
WS2 -->|"prices"| PC
WS3 -->|"prices"| PC
WS4 -->|"prices"| PC
WS5 -->|"prices"| PC
WS6 -->|"prices"| PC
PC --> API["price API
prices API"]
EF -->|"public"| DD["Demo Dropdown
exchanges endpoint"]
style TBCC fill:#4a5568,stroke:#718096,color:#e2e8f0
style EF fill:#2d4a6f,stroke:#4a7ab5,color:#cbd5e1
style EAM fill:#2d4a6f,stroke:#4a7ab5,color:#cbd5e1
style EM fill:#2d5a4a,stroke:#4a9a7a,color:#cbd5e1
style PC fill:#2d5a4a,stroke:#4a9a7a,color:#cbd5e1
style API fill:#4a5568,stroke:#718096,color:#e2e8f0
style DD fill:#3d3a5c,stroke:#6b6399,color:#cbd5e1
style WS1 fill:#334155,stroke:#64748b,color:#94a3b8
style WS2 fill:#334155,stroke:#64748b,color:#94a3b8
style WS3 fill:#334155,stroke:#64748b,color:#94a3b8
style WS4 fill:#334155,stroke:#64748b,color:#94a3b8
style WS5 fill:#334155,stroke:#64748b,color:#94a3b8
style WS6 fill:#334155,stroke:#64748b,color:#94a3b8
Each row defines a complete WebSocket connection: endpoint URL, subscribe message template with {SYMBOLS} placeholder, JSON paths for extracting price/symbol/timestamp from trade messages, timestamp format (RFC3339, unix_ms, unix_ns), ping keepalive interval and payload, and an enabled flag to disable an exchange without a deploy.
Every exchange uses a different symbol format for the same asset. BTC is BTC-USD on Coinbase, btcusd on Gemini, BTC/USD on Kraken, BTC_USDT on Gate.io, BTCUSDT on Crypto.com, and BTC-USDT on OKX. The translation table maps each normalized asset (BTC) to its exchange-specific symbol. 161 rows across 6 active exchanges, zero overlap, all data-driven. Each row carries three control flags: enabled (appears in the subscriber dropdown), prewarm (gets a live WebSocket subscription), and category (dropdown group). The EAM Admin Panel provides a visual interface for managing all rows without writing SQL.
| Endpoint | Purpose |
|---|---|
GET /admin/exchange-feeds | List all exchanges with asset counts and connection status |
POST /admin/exchange-feeds/save | Create or update an exchange configuration (upsert) |
POST /admin/exchange-feeds/toggle | Enable or disable an exchange with one call |
GET /admin/exchange-assets | List asset mappings — returns id, enabled, prewarm, category per row |
POST /admin/exchange-assets/save | Batch create/update asset-to-symbol mappings (includes prewarm and category) |
POST /admin/exchange-assets/toggle | Flip enabled and/or prewarm on a single row — targeted UPDATE, no full save required |
POST /admin/eam/sync | Sync EAM → application_parameters (per-exchange CSV + master list) |
GET /admin/eam/audit | Start 4-layer prewarm audit async — live exchange API, drift check, smoke test |
POST /admin/eam/discover | Discover top uncovered assets for an exchange, ranked by 24h volume |
GET /exchanges | Public endpoint — powers the demo dropdown on the subscription page |
Every price in The Trinity Beast arrives via a persistent WebSocket connection — no REST polling, no scheduled fetches, no stale data. Each container maintains 6 independent WebSocket connections, one per exchange.
| Exchange | Endpoint | Pair Format | Assets | Source Tag |
|---|---|---|---|---|
| Coinbase | wss://advanced-trade-ws.coinbase.com | BTC-USD | 24 | coinbase-ws |
| Gemini | wss://ws.gemini.com | btcusd | 24 | gemini-ws |
| Kraken | wss://ws.kraken.com/v2 | BTC/USD | 24 | kraken-ws |
| Gate.io | wss://api.gateio.ws/ws/v4/ | BTC_USDT | 24 | gateio-ws |
| Crypto.com | wss://stream.crypto.com/exchange/v1/market | BTC_USD | 24 | cryptocom-ws |
| OKX | wss://ws.okx.com:8443/ws/v5/public | BTC-USDT | 24 | okx-ws |
Each feed auto-reconnects with exponential backoff (1s → 60s max), respects the shutdown signal for graceful termination, and stores prices in both the per-exchange WsPriceCache and the main PriceCache via CachePriceLocal. The source exchange is tracked in every API response and every usage log — total transparency.
graph LR
REQ[Price Request] --> T1
T1[Tier 1
sync.Map
Zero Network] -->|"HIT ~0ms"| RESP[Response]
T1 -->|"MISS"| T2
T2[Tier 2
ElastiCache
Sub-ms Network] -->|"HIT ~1ms"| RESP
T2 -->|"MISS"| T3
T3[Tier 3
REST Fallback
Exchange API] -->|"50-200ms"| RESP
WS[6 WebSocket Feeds] -->|"every trade"| T1
style REQ fill:#4a5568,stroke:#718096,color:#e2e8f0
style T1 fill:#2d5a4a,stroke:#4a9a7a,color:#cbd5e1
style T2 fill:#2d4a6f,stroke:#4a7ab5,color:#cbd5e1
style T3 fill:#5a4a2d,stroke:#9a7a4a,color:#cbd5e1
style RESP fill:#2d5a4a,stroke:#4a9a7a,color:#cbd5e1
style WS fill:#3d3a5c,stroke:#6b6399,color:#cbd5e1
In-process Go sync.Map populated by WebSocket feeds. Sub-microsecond reads. No network call. This is the hot path — 99%+ of requests are served here under stress testing with 300s TTL.
Valkey 7.2 on cache.r7g.2xlarge (52 GB). Shared across all 4 containers. Prices written by the sync job and WebSocket feeds. Falls through to Tier 3 only if both Tier 1 and Tier 2 miss.
Direct REST API calls to the corresponding exchange (Coinbase, Gemini, Kraken, Gate.io, Crypto.com, or OKX). Only triggered for assets not in any cache — typically first-time queries for non-prewarmed assets. Result is cached in Tier 1 and Tier 2 for subsequent requests.
The cache TTL is configurable per profile — 13 seconds in production (fresh-price), 300 seconds during stress testing. WebSocket-fed assets stay sub-second fresh regardless of TTL because every trade pushes a new price into Tier 1.
Three generations of UDP optimizations, each targeting a specific bottleneck. The progression from v6 to v8 transformed UDP from a protocol that failed above 1,500 concurrent into one that achieves 100% success at 21,000 concurrent — the first perfect run in Trinity Beast history.
| Version | Optimization | Before | After | Impact |
|---|---|---|---|---|
| v6 | Zero-alloc response builder | json.Marshal (reflection) | buildUDPResponse() — direct byte append | ~70% faster, zero heap allocations |
| Multi-socket architecture | Single shared net.UDPConn | One socket per reader goroutine | 3× write parallelism | |
| Per-socket worker pools | Shared across all readers | Dedicated channel per socket | Zero cross-socket contention | |
| v7 | Manual byte-scan JSON parser | encoding/json.Unmarshal | Direct byte scanning for fields | ~5× faster parsing, no reflection |
| Zero-copy response write | Build → copy → write | Build → write from pool → return | Eliminates 1 alloc per response | |
| v8 | SO_REUSEPORT | Single kernel receive queue | Per-socket kernel receive queue via net.ListenConfig.Control | Eliminated receive buffer bottleneck |
| recvmmsg batch reads | 1 datagram per syscall | 32 datagrams per syscall via ipv4.PacketConn.ReadBatch | ~32× reduction in read syscalls | |
| Pre-serialized response cache | Build JSON per request | sync.Map of pre-built byte slices | ~2× faster for cache hits | |
| 32 MB socket buffers | 8 MB per socket | 32 MB per socket | Absorbs burst spikes before drops | |
| 8 reader goroutines per protocol | 3 readers | 8 SO_REUSEPORT sockets × 128 workers = 1,024 handlers | More packets drained before drops |
Result: 100% UDP success through all 13 concurrency levels (30 to 21,000 concurrent). 487,900 UDP RPS sustained for 30 minutes. 0.2ms average latency. The v8 engine combined with persistent socket pools in the stress client eliminated every bottleneck in the UDP path.
Every container runs 24 atomic.Int64 counters that track the complete request lifecycle in real-time. The overhead is approximately 1 nanosecond per increment — invisible at any throughput level.
tcp_requests, udp_requests, lrs_requests — real-time RPS by protocol
syncmap_hits, elasticache_hits, cache_misses — three-tier visibility
udp_packets_received, udp_packets_dropped, udp_packets_sent — packet loss detection
bg_work_submitted, bg_work_dropped, bg_work_completed — housekeeping saturation
batch_rows_queued — SQS messages sent (usage log entries queued for Lambda consumer)
db_open_conns, db_in_use_conns, db_wait_count — pool utilization
Access via GET /admin/stress-stats — returns all 24 counters plus derived metrics (RPS, hit percentages, drop rates) in a single JSON response. Reset with GET /admin/stress-reset before each test run. Six key metrics are also published to CloudWatch for dashboard visibility.
Each container publishes its 24-counter metrics snapshot to ElastiCache every 3 seconds. The /admin/cluster-stats endpoint reads all 4 snapshots in a single ElastiCache pipeline call — one round-trip, sub-millisecond, guaranteed all 4 containers.
graph LR
subgraph Containers
M[BeastMain
24 counters] -->|"every 3s"| EC
Mi[BeastMirror
24 counters] -->|"every 3s"| EC
L[BeastLRS
24 counters] -->|"every 3s"| EC
end
EC[(ElastiCache
cluster:stats:*
TTL 30s)]
EC -->|"1 pipeline read"| CS[/admin/cluster-stats/]
CS --> TBCC[Command Center
Cluster Health Widget]
CS --> CW[CloudWatch
6 Runtime Metrics]
style M fill:#334155,stroke:#64748b,color:#94a3b8
style Mi fill:#334155,stroke:#64748b,color:#94a3b8
style L fill:#334155,stroke:#64748b,color:#94a3b8
style EC fill:#5a3a3a,stroke:#8a5a5a,color:#e2c8c8
style CS fill:#2d5a4a,stroke:#4a9a7a,color:#cbd5e1
style TBCC fill:#2d4a6f,stroke:#4a7ab5,color:#cbd5e1
style CW fill:#3d3a5c,stroke:#6b6399,color:#cbd5e1
| Key | TTL | Content |
|---|---|---|
cluster:stats:BeastMain | 30 seconds | Full metrics snapshot + cluster_node + region + published_at |
cluster:stats:BeastMirror | 30 seconds | Same structure |
cluster:stats:BeastLRS | 30 seconds | Same structure |
If a container hasn't published in 30 seconds, its key expires and it shows as missing in the cluster view — an immediate signal that something is wrong. The publish interval (3 seconds) and TTL (30 seconds) are candidates for future application parameters.
Before: 30 HTTP requests through the ALB, hoping the load balancer routes to different containers. Slow, unreliable, wasteful.
After: 1 ElastiCache pipeline read. Sub-millisecond. Guaranteed all 4 containers. The data is always fresh because each container publishes independently every 3 seconds.
GET /admin/cluster-stats returns per-node snapshots and aggregated totals:
per_node — array of 4 snapshots, each with cluster_node, region, published_at, and all 24 countersaggregated — summed counters across all 4 containers with recomputed percentagesnodes_found / nodes_expected — instant health indicatorregion — AWS region (us-east-2)AWS Partners connect via PrivateLink (TCP) or VPC Peering (UDP) directly to containers. Partner API keys bypass all rate limiting, monthly caps, and billing checks — in both the TCP and UDP handlers.
The exchanges we depend on — Coinbase, Gemini, Kraken, Gate.io, Crypto.com, OKX — share their data with us at no cost. We pass that forward. If your AWS application needs live crypto prices, we provide them free. We receive freely, we give freely.
Partners apply through a public form at /partner-apply.html, receive a professional SES confirmation email, and can check their application status at /partner-status.html. Applications are reviewed in the TBCC Partner Management widget.
16 named profiles stored in Aurora's application_parameter_profiles table. Each profile defines a complete set of tuning parameters — rate limits, cache TTLs, connection pool sizes, batch settings, and logging levels. Applied instantly via GET /admin/system-mode?mode=<name>.
| Category | Profiles | Key Difference |
|---|---|---|
| Production | demo, debug, fresh-price | TTL, logging, pool sizes |
| LPO Stress | stress, tcp-direct, tcp-alb, udp-direct, udp-nlb | Flush intervals, batch sizes, pool topology |
| LRS Stress | lrs-direct, lrs-alb, lrs-udp-direct, lrs-udp-nlb | db_max_open=180, cache_read_ms=1000 |
| Combined | combined-direct, combined-alb, combined-udp-direct, combined-udp-nlb | db_max_open=180 for LPO+LRS headroom |
Key tuning rule: db_max_idle always equals db_max_open — the fix that dropped p99 latency from 1,266ms to 8.9ms. All cache pool sizes are multiples of 3 (one pool per container).
Usage logs are never written synchronously — and never written directly to Aurora from the hot path. Every price request fires a message to SQS via a channel-buffered producer. A purpose-built Go Lambda (trinity-beast-queued-writer) consumes batches from the queue and batch-inserts into Aurora. Zero logs shed. Zero latency added to the price response.
sqs_batch_size — messages per SQS SendMessageBatch call (default 10, max 10)sqs_flush_ms — flush interval in milliseconds (default 100, stress: 50)sqs_buffer_size — channel buffer capacity (default 50,000, stress: 100,000)sqs_timeout_ms — per-batch SQS API call timeout (default 3,000ms)Messages use a type-routed envelope format ({"type":"usage_log","payload":{...}}) — extensible to any future write type without changing queue or Lambda infrastructure. During Run 17 at 746,374 combined RPS, every usage log was delivered to Aurora via SQS with zero shedding — solving the data integrity gap discovered in earlier stress tests where only ~12K of 1.34B requests produced Aurora rows.
The consumer Lambda folds each batch's per-key usage increments into a single set-based UPDATE rather than one statement per key: UPDATE api_keys SET current_usage = current_usage + data.increment FROM (SELECT unnest($1::text[]) AS api_key, unnest($2::int[]) AS increment) AS data WHERE api_keys.api_key = data.api_key. A 100-message batch touching N distinct keys becomes N → 1 round-trips to Aurora.
A cluster-wide TCP connection throttle coordinated via ElastiCache. Each container tracks its success rate over a rolling window. When the rate drops below the threshold, the governor introduces a configurable delay to shed load gracefully — preventing cascade failures under extreme concurrency.
Disabled during direct-to-container stress tests (where we want to find the raw ceiling). Enabled during ALB/NLB tests (where we want production-like behavior).
One Docker image. One Go binary. Four operational modes controlled by the SERVER_TYPE environment variable:
| Mode | SERVER_TYPE | Services | Ports |
|---|---|---|---|
| LPO Only | APP_SERVER | Price API + UDP | 8080, 8081 (health), 2679 |
| LRS Only | REPORT_SERVER | Reports + UDP | 9090, 9091 (health), 2680 |
| Combined | APP_REPORT_SERVER | All inbound services | 8080, 8081, 9090, 9091, 2679, 2680 |
| Webhook | WEBHOOK_SERVER | Outbound price push | 8083 (health only) |
All 4 ECS services run the same image. The only difference is the environment variable. This means one build, one push, one image — deployed to 4 services with different configurations. The Webhook service is outbound-only (no ALB) — it pushes prices to Associates via UDP + HTTPS on a configurable schedule.
Zero hardcoded credentials or email addresses. Everything sensitive is loaded from AWS Secrets Manager at startup and injected into the Config struct. 16 keys covering database credentials, Stripe API key, SMTP settings, and all SES sender addresses.
To change a sender email address, update it in Secrets Manager and restart the container. No code deploy, no binary rebuild.
The infrastructure uses two translation systems: AWS Translate for real-time API responses (support tickets, map captions), and a custom Bedrock-powered engine for document translation. Both use ElastiCache as a persistent cache. Language is not a barrier — the system handles it transparently.
| System | Use Case | Languages | Technology |
|---|---|---|---|
| Real-Time API | Support tickets, map captions, user-facing text | 75+ (all AWS Translate languages) | AWS Translate neural MT |
| Document Translation | Technical documentation library (37 docs) | 11 (internal website) | Custom Bedrock engine with sentinel preprocessing |
| Service API | Customer-facing translation via /translate | 21+ (all Bedrock Claude supported) | Bedrock Claude via API |
| Component | Location | Purpose |
|---|---|---|
translateText() | internal/handlers/support.go | Core translation function — calls AWS Translate API with graceful fallback |
PublicTranslateHandler | internal/handlers/support.go | Public POST /translate endpoint for map caption translation |
getSupportEmailStrings() | internal/handlers/support.go | Multi-language email chrome (headings, labels, buttons) — hardcoded in Go |
| ElastiCache cache | translate:{lang}:{hash} | 30-day TTL cache for translated text — avoids repeat API calls |
Refund confirmation emails are sent in the customer's preferred_lang (stored in the users table). Both translation purchase refunds and subscription refunds are localized across 12 languages using the same hardcoded-struct pattern as support emails.
| Component | Location | Purpose |
|---|---|---|
GetRefundEmailStrings() | internal/handlers/refund_email.go | Multi-language email strings (headings, labels, body text, footer) — 12 languages |
BuildTranslationRefundHTML() | internal/handlers/refund_email.go | Gmail-compatible HTML builder for translation refund emails |
BuildSubscriptionRefundHTML() | internal/handlers/refund_email.go | Gmail-compatible HTML builder for subscription refund emails |
TestRefundEmailHandler | internal/handlers/refund_email.go | Admin endpoint POST /admin/test-refund-email — sends test emails with dummy data |
sendSubscriptionRefundEmail() | trinity-beast-receipt-lambda | Sends localized refund email on Stripe charge.refunded webhook |
Technical documentation requires more than neural machine translation — code blocks, diagrams, brand names, and version numbers must survive intact. The custom Bedrock-powered engine uses sentinel preprocessing to protect technical content, multi-layer validation to ensure structural integrity, and Step Functions orchestration for fire-and-forget operation.
Full documentation: AutoOps Translation Engine
translateText(message, lang, "en") → stored in message_entranslateText(reply, "en", lang) → stored in message_translated, sent via SESPOST /translate → check ElastiCache → on miss, call AWS Translate → cache result for 30 daysPOST /admin/translate → SQS → Step Functions → Bedrock worker → S3 deploy → CloudFront invalidation. Use options.delta = true to skip language pairs where the translated file is already newer than the source — saves up to 90% on incremental updates.Cache key: translate:{target_lang}:{hex_of_source_text}
TTL: 30 days (translations are deterministic — same input always produces same output)
Cost impact: ~100 map pins × 11 languages = 1,100 one-time translations. After initial population, every request is a sub-millisecond ElastiCache hit. Total one-time cost: ~$0.02.
Internal website (12 languages): English, Spanish, Portuguese, French, German, Russian, Hindi, Urdu, Italian, Arabic, Japanese, Chinese (Simplified). All documentation and UI is translated into these 12 languages.
Service API (21+ languages): The translation service exposes all languages supported by Amazon Bedrock Claude — customers can translate to any language the model handles reliably, including Italian, Korean, Indonesian, Bengali, Turkish, Vietnamese, Thai, Polish, Dutch, and more.
The ECS task role (ecsTaskRole) has an inline policy TranslateAccess granting translate:TranslateText permission. The translation worker task role has bedrock:InvokeModel permission for Claude Sonnet. No VPC endpoint required — both APIs are accessed via public AWS endpoints.
A round of PostgreSQL optimization pushed aggregation and frequent-query work down into Aurora and removed per-query overhead on the hot paths. The principle: let the database do what databases are good at, prepare the queries that run constantly, and measure every change against the live engine before keeping it.
dbx)A thin seam over database/sql registers the five fixed-shape, high-frequency queries as named prepared statements at startup: API-key lookup, API-key last-used touch, application-parameters load, report-count check, and report-count upsert. It is deliberately not an ORM or query builder — handlers issuing dynamic SQL keep calling *sql.DB directly. The registry is nil-safe and fail-soft: if a statement fails to prepare, it transparently falls back to an ad-hoc query, so a registration problem can never block server startup. Startup logs dbx: registered 5 hot-path prepared statements.
INSERT … ON CONFLICT DO UPDATE with month/day rollover logic, removing a round-trip on every report request.UPDATE … FROM (unnest(...)) (see section 10), turning N round-trips into 1 per batch.ANY($1).The admin analytics summary replaced six separate aggregation queries with a single GROUPING SETS pass that also computes latency percentiles (percentile_cont p50/p95/p99) inside the engine. Measured 2.1× faster against live Aurora — 87 ms to 41 ms, six round-trips to one.
Database self-observability (the /admin/db-insights endpoint) showed usage_logs doing sequential scans on filtered analytics queries. Four (timestamp, dimension) composite indexes — on asset, API key, source, and cluster node — let the planner use index scans instead (6–8 ms execution). Per-day rollups (totals, latency percentiles, cache-hit rate, cardinality) are precomputed by the mv_usage_daily materialized view, served via /dashboard/api/admin/daily-rollup. The view is refreshed every 5 minutes by the pg_cron job tbi-mv-usage-daily-refresh running inside Aurora, using REFRESH MATERIALIZED VIEW CONCURRENTLY so readers never block.
The /admin/db-insights endpoint surfaces the buffer-cache hit ratio (currently ~99%), the top queries by total execution time and call count from pg_stat_statements, and per-table sequential-vs-index scan health — the same evidence that justified the composite indexes above. A companion /admin/db-insights/reset clears the pg_stat_statements baseline for clean before/after measurement windows.
SQL injection eliminated. The /admin/sql endpoint gained an optional args array for parameter binding, and the translate-finalize Lambda's interpolated SQL was converted to placeholders — there is no value-interpolated SQL left in the active codebase.
100% of subscription revenue from The Trinity Beast goes directly to Cross Power Ministries of Pakistan — funding freedom from brick kiln debt bondage, clean water, medical camps, wheelchairs, education, and Bibles. When a developer calls /price?asset=BTC, they're not just getting a number. They're funding freedom.
This is not a feature of the Go application. It is the reason the Go application exists.