cd ../case-studies

// case study 02

From one overloaded server to an isolated, secure fintech platform

Fintech Go AWS 6+ developers 2 months
1,000+ transactions a day, up from a server that struggled at 80–100
1 server exposed to the internet: the gateway
0 downtime on production deploys
0 secrets left in code or config files

The situation

A fintech client had built its platform in Go. At launch, everything ran on a single VM: the application, the database, the cache and internal tools. Under load the server hit high CPU and crashed, and customers sometimes saw timeouts. It struggled at 80–100 transactions a day. Developers built and deployed binaries by hand, and secrets sat in .env and appsettings.json files.

The new architecture

public Internet
only public VM Gateway · Caddy
private subnet App · Go binary
app VM only Database
app VM only Cache · Valkey

Each layer accepts traffic only from the one in front of it.

What changed

isolation & security

Split the single server into separate gateway, app, database and cache VMs. Only the Caddy gateway faces the internet; everything else talks over private subnets. The Go binary runs under its own restricted user that can only manage its own systemd service. The database has separate read and write users.

right-sized servers

Each server is sized for its job: only the database runs on a larger instance, while the gateway, app and cache run on small ones. The load that crashed one machine is now spread across four.

automated, gated releases

Replaced manual deploys with GitHub Actions pipelines for dev, staging and production. Production deploys only after linting, a vulnerability scan, system and configuration checks and business-logic tests pass. Deploys have zero downtime. A release that fails any check is never deployed: the team is notified and the running version stays exactly as it was.

secrets, backups & visibility

Moved every secret to AWS Secrets Manager with rotation policies, read directly by the app. Automated database backups to S3. Designed logging to Grafana and error reporting to Sentry, which the client's developers implemented. Valkey handles rate limiting, user lookups and auth tokens.

release.log — what a failed release looks like
release → production  lint ................. ok  vulnerability scan ... ok  system checks ........ ok  config checks ........ ok  business-logic tests . FAILED✗ Release blocked. Nothing was deployed.  team notified · production unchanged, still serving the current version

Results

  • Grew from struggling at 80–100 transactions a day to handling 1,000+
  • No more crashes or timeouts from one overloaded server
  • Only the gateway is exposed to the internet
  • Broken builds never reach production, and deploys cause no downtime
  • More releases, deployed more often each day, with confidence
  • Faster responses, with Valkey handling rate limits, user lookups and auth tokens
  • Met the payment vendor's compliance requirements

Stack

Go AWS EC2 Caddy Valkey systemd GitHub Actions AWS Secrets Manager Amazon S3 Grafana Sentry Linux
related reading Right-sizing without breaking production read post →

Client details are anonymized to protect confidentiality.

Outgrowing your first server?

Let's talk it through. 30 minutes, free.

Book your free 30-min call