All projects

We cut VerifyEd's hosting costs by ~75%

How we audited VerifyEd's AWS setup, merged two repos into a monorepo and moved the platform to Render, cutting monthly hosting costs by about 75%.

We cut VerifyEd's AWS bill by 75%, around $9.6k a year, beside a VerifyEd learner profile

VerifyEd issues trustworthy, shareable digital certificates. Education providers use it to award credentials to their learners, and every credential is anchored to the XRP Ledger so anyone can check it's genuine.

The product worked. The problem was what it cost to run.

Every part of VerifyEd was hosted on AWS: the frontend and API on Elastic Beanstalk, the database on RDS, Redis on ElastiCache, with CloudFront and WAF in front and CodePipeline handling deploys.

The monthly bill had grown past $1,000, and because so much of the platform was wired into AWS-specific services, there was no quick way to bring it down.

Over a few weeks in October and November, we:

  • Audited every line of the AWS bill against what the application actually needed
  • Merged the separate frontend and backend repositories into one monorepo, keeping the full history of both
  • Simplified the application so it could run on smaller, cheaper servers
  • Moved the frontend, API, database and Redis to Render, with the whole setup defined as code
  • Kept the few AWS services that still earned their place
  • Cut the monthly hosting bill by about 75%, saving roughly $9,600 a year

Where VerifyEd was

Nothing about VerifyEd's setup was badly built. It was set up the way AWS makes easy: every piece sensible on its own, and together far more infrastructure than an app of VerifyEd's size needs.

That's often the trap with a large cloud provider.

Each service is billed separately, each one quietly assumes the others are there, and the total creeps up without any single decision feeling expensive. By the time the bill is a problem, moving off it is a whole lot of friction.

For a startup watching its runway, that's a real constraint. Money spent on idle infrastructure is money not spent on the product.

Auditing the bill

We started with VerifyEd's October bill and asked four questions of every service:

  • Does the app actually need this?
  • Is it the right size for the traffic and data it handles?
  • Is the setup more complex than the application requires?
  • Could the same job be done for less somewhere else?

A few things stood out straight away.

  • The databases were close to half the bill. That covered a production database holding only a few gigabytes of data, plus a separate test database alongside it.
  • Networking was about a sixth of the bill. A client VPN, NAT gateways and public IP addresses.
  • Servers and load balancers. Elastic Beanstalk servers for the frontend and API, with load balancers in front: a setup built to spread traffic across many servers, for traffic that fits on one.
  • The long tail. Two Redis caches, WAF protection packs, the build pipeline, logs and alarms and old disk volumes.

Individually, none of these looked alarming. Together, though, they were most of the bill.

Making the app lighter

Some of the cost came from the application itself, so we looked at what it was asking its servers to do.

The API ran a headless copy of Chrome to turn certificates into PDFs and images. That alone needed around 2 GB of memory per server. We moved certificate downloads into the browser instead, so the person downloading a certificate does the rendering, and the API no longer needs a server sized around Chrome.

The frontend sporadically used server-side rendering too, to no huge benefit, which meant it needed its own server. We turned it into a plain client-side app, so it now ships as static files from a global CDN, at no cost.

Neither change was free of trade-offs, so we weighed each one against what it cost to keep it running.

One repository instead of two

VerifyEd's frontend (Angular) and API (Express and Postgres) lived in two separate repositories. We merged them into a single monorepo, keeping the full git history of both, so nothing about how the code got here was lost.

This makes the platform simpler to look after in two ways:

  • AI tooling sees the whole system. A change to the API and the screen that calls it sit in the same place, so AI coding tools can read and change both together instead of guessing at the other half.
  • Maintenance has one home. One place to clone, one CI pipeline, one set of docs and one runbook for whoever looks after the platform next.

Continuous integration only builds and tests the app that changed, and each app only redeploys once those checks pass. A frontend tweak never redeploys the API, and a failing test never reaches production.

Moving to Render

With the bill audited and the app slimmed down, we moved the bulk of the platform to Render.

From our experience launching and maintaining products, Render often has a nice balance of a decent developer UX alongside a reasonable price that scales with you.

The whole setup is described in one Render Blueprint file that lives in the repo: the frontend as a static site on Render's CDN, the API as a Docker service, a managed Postgres database, and Render's Redis-compatible Key Value store for the background job queue.

Every service is sized to what VerifyEd actually uses. The API and database each run on a smaller CPU, the database has plenty of disk headroom over the data it holds today, and the Key Value store is persisted to disk so queued jobs survive a restart.

We also set up a separate staging environment on Render's free plans. It's a full copy of the stack, so changes can be tried safely before they reach production.

We didn't move everything for the sake of it. A few AWS services were either inexpensive or held data that was safer left where it was, so they stayed.

The cutover

We rehearsed the whole migration on staging first: a full copy of the database, then smoke tests covering sign-in, uploads, certificate downloads, issuing a credential all the way through to the XRP Ledger, and payment webhooks.

On the day, the order mattered:

  1. Lower the DNS time-to-live in advance, so the switch would take effect within a minute.
  2. Stop all background work on AWS and wait for the credential anchoring queue to empty, so no credential was lost or anchored twice.
  3. Copy the database across to Render.
  4. Point VerifyEd's existing domains at Render.

Because the domains didn't change, payments and sign-in integrations carried on without any changes. Once production was settled on Render, we removed the old AWS services, keeping final database snapshots as a safety net.

The outcome

VerifyEd's AWS bill for October 2026 was $1,056. Running the same platform on Render, plus the AWS services we kept, is projected at about $240 to $265 a month.

That's a saving of about 75%, or roughly $9,600 a year, money that now goes back into the business rather than into idle infrastructure.

Just as important, the platform is simpler than it was. One repository, infrastructure defined as code, deploys that only touch what changed, and a staging environment to test against. It's easier for VerifyEd's team to run, and easier for AI tools to work on.

Need help optimising your product or cutting infrastructure bills? Get in touch with us to discuss what we can do for you.