I run a tiny website for tracking item prices in Guild Wars 2, gw2roar.com. I don’t run it for the money (it has 1 or 2 visitors per day), it’s simply a fun site that suits my needs.

Because it doesn’t make money, every penny of running cost comes out of my pocket. When I first started the site, it was all 12 month free tier AWS services so I didn’t care about cost and then I took part in an Alexa promotion that gave me a $100 credit against my monthly bill. All good things come to an end as they say. After I got notification that the promotion was ending, I started looking at how I could significantly reduce my costs.

Step 1: Use the Cost Explorer to find the high cost services

Open up Cost Management and click on the Cost Explorer in the list on the left.

In this view you can explore the costs of each service you use.

I had two spikes in my cost explorer, Elasticache and RDS. Elasticache stores candlestick data per item per day for quick retrieval. RDS runs a postgres instance that stores the item price data retrieved every 30 minutes from the Guild Wars 2 API.

Step 2: Imagine your site without the high cost service

What if Elasticache didn’t exist?

Calculating candlestick data on the fly is slow and the result never changes after a day is done and I used Elasticache to speed up loading times.

Ultimately I needed a quick, distributed cache I could query by item id and time. Elasticache isn’t the only service that provides that, I could move to nearly any distributed cache. My decision ultimately came down to cost.

Step 3: Cost up the changes

The AWS pricing calculator has gotten much easier to use over the past few years. Now that you can easily price by service there’s less room for missing out or adding in costs by mistake.

A 1 node, t2.micro ElastiCache cluster costs about $12.41 per month.

What would the price be if I switched to, say, DynamoDB?

DynamoDB is a bit more difficult to price, you need to know:

  • the size of your data
  • the baseline read/write rates
  • the peak read/write rates
  • how long the peaks last
  • what different options and features mean

I used the information from ElastiCache to estimate the size of the data and the web statistics to estimate the read capacity. The write capacity was harder to estimate because it came from two sources.

A visitor could cause a write by loading the data for an item, but that would be at a much frequency lower than the number of users on the site. So the baseline write rate is very low.

At the end of every month a batch job calculates and loads all the data for the month into the cache. Given I knew how many items there were, and that the data needed to be loaded within 15 minutes (the timeout of a Lambda function), I could work out what the peak write rate would be.

Did I need:

  • reserved capacity? no, that would drive up the cost and provide no benefit at a low rate of reads/writes
  • on-demand capacity? It’s nice in theory to pay for what you use, but in practice it would be more expensive for my site than using provisioned capacity and auto-scaling.

With everything in the calculator, AWS predicted a cost of about $3.20 per month. However, the calculator doesn’t take into account the “always free” alowances, so switching to DynamoDB would actually bring my costs to 0.

Step 4: Make the changes and evaluate

The cost estimation is just an estimation. The real world can be different.

For example, with my first implementation of the switch to DynamoDB, I put some of the code into the same Lamdba function that called RDS. That function was running in the RDS VPC, and it’s quite simple to set up a VPC endpoint for DynamoDB. So easy that I missed that this would cost me $0.01 per AZ per hour.

Thankfully I saw the costs within the first few hours of creating the endpoint and was able to re-architect my functions.

Watching and evaluating the costs is essential to finding out fast if your estimates were wrong.

Step 5: Repeat from Step 1

Keep hunting for options and reducing costs until you’re satisfied.