One of the major challenges of using Ymir to host a WordPress site on AWS Lambda is estimating cost. AWS uses usage-based pricing for a lot of its services. This makes calculating the cost of hosting a WordPress site on AWS challenging.
I’ve been running my personal site on AWS Lambda for a few months now. This has given me a few months of data on the cost of host a WordPress site using Ymir. While this is just one example, it’s still an excellent opportunity to look at the real world cost of using AWS Lambda to host a WordPress site.
Caveats
Before we begin, it’s worth noting a few drawbacks to the analysis that we’ll see in this article.
First, this won’t be very complex cost model. We’re going to look at costs and traffic for a period. We’ll then use that data to see how much it costs per 1,000 visits.
The region that you have your project in can also impact your cost. I’m using US-EAST-1 which is the cheapest region. If you’re in a more expensive region, you might pay a bit more for certain services.
It’s also worth noting that the bills that I have include the AWS free tier for certain services. We want to exclude anything that we got for free. So we’re going to extrapolate the full cost of the service for the month.
In a similar vein, this AWS account is also the one that I use for the development of Ymir. This means that some services have costs that aren’t related to hosting my personal site. We’ll go over those and estimate the actual cost using historical billing.
Next, there’s media usage. Some WordPress use a lot of images and video. Others don’t. This amount of media that your WordPress site uses affects your costs.
In my case, my personal site is a technical site where I write programming articles. It’s mostly text with a few images. This means that I have lower than average media hosting costs.
Last, there’s the Ymir project configuration. The default Ymir project configuration tries to minimize your costs as much as possible. But some project configuration options, such as a private subnet with a NAT gateway, can increase your costs significantly.
The data
With this out of the way, let’s bring in the data! Below is the bill for June 2021. It’ll be the main bill that we’ll look at for this analysis.
Next, we need the traffic information for the website. I use Fathom Analytics to track visitors. You can see the traffic details for June below.
So this is our initial data. I paid $29.39 to AWS in June 2021. And during that period, I had 13,400 visits to my personal site.
Breaking down usage costs
Now that we have everything, we’ll start breaking down the costs. We’re going to start with the usage-based services. This will allow us to calculate how much a visit costs.
If you’d like to see how all these services work together when using serverless WordPress, you can check out this article.
API Gateway
The first usage-based service in the bill is API Gateway. This service acts as the bridge between AWS Lambda and the internet. I paid $0.54 for 537,975 requests.
The only thing worth noting about this cost is the number of requests is a lot higher than the visits. That’s because not all traffic will show up as visits in your analytics platform. For example, search engines indexing your site.
This highlights the limit of using data from an analytics platform as a proxy for website requests. It’s still a useful enough metric for this exercise. But it’s worth remembering that it’s not the real amount of visits your site received.
CloudFront
Next in the bill is CloudFront. This is the AWS content delivery network. I paid $3.46.
Parsing a CloudFront bill is more work because it’s broken down by region. But if we look at the United States region, you can see that most of the costs come from requests and bandwidth. Bandwidth is also going to be the larger unknown on a project since it varies depending on how much media your WordPress site has.
CloudWatch
After CloudFront, the following bill item is CloudWatch. This is where all your AWS logs go, and it’s also what runs WP-Cron. While CloudWatch shows as $0.00 on the bill, that’s only because of the AWS free tier. CloudWatch will always cost a bit each month because of AWS Lambda logs. (Each Lambda requests has two mandatory log entries.)
If we expand the CloudWatch bill item, you’ll see that my personal site generated 0.221 GB of logs. The first 5 GB are always free, but you can hit that easily if you’re not careful. (CloudWatch logs are one of the common AWS bill surprises.) By default, Ymir keeps your log clean so it would take a lot of Lambda requests to hit 5 GB.
But if we weren’t using the free tier, how much would 0.221 GB of logs cost? Well, it’s $0.50 per GB. So our basic log usage would be $0.11.
Data transfer
Next up is “Data transfer”. Data transfer represents the cost of moving data between various parts of AWS. It’s another common bill items that can cause unexpected surprises.
Ymir tries to keep your data transfer costs as low as possible. That’s why the bill is $0 with the free tier. The impact of the free tier is hard to calculate here. But based on previous bills, that free tier comes up to roughly $0.10.
That said, they will vary depending on your media usage. That’s because the primary source of data transfer is the media used by your site. You have to pay to transfer your media files between S3 and CloudFront.
So if you don’t use a lot of media files, your data transfer costs will be low. If you’re a media heavy site, you can expect a heftier bill for data transfer.
DynamoDB
DynamoDB is a potential cost item if you use the Ymir WordPress object cache. But for now, the cost that you see here is due to Ymir’s automated test suite. So we can ignore that $0.00 charge.
EC2 container registry (ECR)
The same goes for the EC2 container registry. It’s only a cost item if you use container image deployment. Here, the $0.01 charge comes from Ymir’s development. (The feature was developed that month.)
Elastic compute cloud (EC2)
Elastic compute cloud (EC2) is a scary item in the bill. It’s $6.91 which is the second largest item after RDS. But the good news is that you can completely ignore it!
That’s because all the costs come from Ymir’s automated test suite. You’ll only see EC2 in your AWS bill if you use a bastion host or a NAT gateway. And as you can see, most of the cost is from the NAT gateway which is why I warned that it can significantly increase your costs.
Key management service (KMS)
Key management service (KMS) is an important AWS service. It’s the service that handles the encryption and decryption of data on AWS. You might not expect to see KMS on your AWS bill, but it serves a critical purpose.
KMS handles the encryption and decryption of your project secrets. By default, this is all your database credentials. But if you add more secrets, they are all encrypted using KMS.
The Ymir Lambda runtime will minimize requests to KMS by injecting the decrypted keys into the runtime. But you will still see some cost associated to it. This cost will scale based on how many requests your site gets each month.
KMS comes with a free tier for 20,000 requests. After that, it costs $0.03 per 10,000 requests. If we ignore the free tier, the actual KMS cost for the month was $0.17.
Lambda
Now, we’re at the bill item many people worry about: Lambda! Lambda is a complex beast to predict pricing for. That’s because AWS bills you for how many requests Lambda received, but also how long each request takes and how much memory it used.
Ymir tries to reduce these variables as much as possible. Page caching reduces requests and Ymir will give your Lambda runtime as little memory as possible by default. But you can still control the memory used by Lambda in your project configuration.
Lambda also has a very generous free tier. So much so that you might not see a charge for Lambda until your WordPress site reaches 15,000 visits or more. But this will depend on your project configuration.
Now, I didn’t pay anything with the free tier. But how much would have I paid without it?
Let’s start with requests. Lambda costs a flat $0.20 per million requests. So excluding the free tier, I’d have paid $0.14 for 675,287 requests to Lambda.
For the execution, Lambda charges $0.0000166667 for every GB-second. It’s a really difficult metric to estimate for. But since we know how many GB-second we used, we can see the actual cost easily. Without the free tier, I’d have paid $5.03 for the 301,904 GB-second Lambda used.
Route53
After Lambda, we have Route53. Route53 is the AWS DNS service. If Ymir manages your DNS (recommended), you’ll see some costs associated with it.
There are two cost categories to the Route53 bill sections: queries and hosted zones. The hosted zones section is a fixed cost, which we’ll cover later. The queries section is how many queries your DNS server received for DNS records. This scales with traffic.
I paid $0.06 for 158,402 queries.
Simple storage service (S3)
The last usage based service is the simple storage service better known as S3. S3 is without question the better known service by AWS. A lot of WordPress sites already use it to store their media library files. This is also what Ymir uses it for, but it’s also where all your asset files go during deployment.
S3 has different costs associated with it. There’s storage cost which is fixed. (We’ll talk about it later.) But also cost per request, which is broken down into two request types.
Most of the requests costs come from PUT, COPY, POST, or LIST requests. These are requests that only happen when you deploy.
In this case, they’re due to Ymir’s development and not hosting my personal site. I only deploy the site 1-2 per month. Meanwhile, I do hundreds of deployment per month developing Ymir. In practice, you’ll pay $0.01 unless you’re doing dozens of deployments per month.
The other request cost is for GET requests. These happen whenever someone makes a request for something stored on S3. These requests were all for my personal site and weren’t part of Ymir’s development.
Since S3 has no free tier, there’s no need to evaluate anything more. We can just add both storage and GET request costs. This puts our real S3 cost at $0.02.
Calculating the cost per visit
Now that we’ve gone over all our usage based bill items. We can calculate the real cost per visit for carlalexander.ca. All the costs are:
API Gateway | $0.54 |
CloudFront | $3.46 |
CloudWatch | $0.11 |
Data Transfer | $0.10 |
Key Management Service (KMS) | $0.17 |
Lambda | $5.03 |
Route53 | $0.06 |
Simple Storage Service (S3) | $0.03 |
Total | $9.50 |
So we get a total of $9.50 for 13,400 visits. If we go further and calculate the cost per visit, the cost becomes $0.71 per 1000 visits. This is probably near the low end of what you can expect for costs per visit.
It’s still possible you could get even cheaper costs per 1000 visits. But it’ll depend on how much of that hidden traffic discussed earlier you get. For 13,400 visits, 675,287 requests were made to Lambda. If you got half of that, your cost would be closer to $0.50 per 1000 visits.
This is the big caveats with trying to estimate usage costs with serverless. There are a lot of variables to factor in and it’s hard to get the big picture. That said, this is still a representative cost estimate for a site receiving a decent amount of monthly traffic.
Fixed costs
Unfortunately, your AWS costs don’t end here. There are also services that charge you per month. You need to take these in consideration when calculating your costs.
The good thing with fixed costs is that they’re a lot easier to predict than the usage based costs. If you know how big your media library is, how many domains you want to manage, how many database servers you need, you can know your costs before doing anything.
Another good thing with fixed cost is that most of them can be spread over projects. So the more projects you have using these fixed cost resources, the less they end up costing per project. Because I’m only using Ymir to host my personal site, I can’t leverage that fact, which increases how expensive it is for me to host it on AWS.
Relational database service (RDS)
The big one is the relational database service (RDS). This is the AWS service that hosts your database. RDS is expensive and is often the largest contributor to someone’s AWS bill.
Here, RDS more than doubles my AWS bill. This is while using the smallest database server possible with as little storage as possible.
Now, some of the RDS cost comes from Ymir’s development. But it’s safe to assume $14 to be about the lowest amount you can pay for RDS.
So if you’re only using Ymir to host a single site, RDS can increase your hosting cost significantly. This is the case with my personal site. I’m paying a lot for a database server that sees barely any use.
On the other hand, if you have a lot of websites, you can use one RDS database server for all of them. You can then split the cost of it over all those different websites. I built Ymir with this use case in mind.
You can create as many databases and database users as you need. You can then add them to your project configuration. Ymir will use the correct users and databases for your projects.
Route 53
We’re back to evaluating Route53 hosted zones. Hosted zones are domains managed by Route53. It costs $0.50 per domain per month.
I’m paying $5 for this, but those are mostly testing domains. carlalexander.ca is only one domain. So the real hosted zones cost is $0.50.
Simple storage service (S3)
Going back to the S3 section of the bill, we can see that I paid $0.14 for 6.1 GB of storage. The primary thing that will affect your S3 storage costs is your media library. If you have a very large media library, you can expect to pay more for storage. Here, it’s not so much my media library that’s taking that space so much as other Ymir projects that I use for its development.
That said, S3 storage prices are really inexpensive. Even if you had a 100 GB of media, you’d only pay $3. So the size of your media library shouldn’t have a significant impact on what you pay for S3. The request cost that we saw earlier will always have a larger impact.
Ymir
It would be disingenuous to not put Ymir as a fixed cost. It’s totally something you need to consider when evaluating everything! So that’s another $39 on top of everything else so far.
Total cost of hosting
Tabulating everything, we get a fixed cost of $54.20. If we add it to usage-based cost, we get a total of $63.70. Even if you exclude the cost of Ymir, it’s still $24.70. That’s a lot for one site getting 13,400 visits!
This is why I wouldn’t recommend Ymir if you’re looking to host just one low traffic site. I do it because I want to dogfood Ymir. But the reality is that your fixed costs are just too much to make this an attractive option.
Ways to reduce costs
Ymir already does as much as possible to reduce your costs. But there are few things you can do to reduce your costs further.
Using a free content delivery network
You can also reduce some of your usage cost by switching to a free content delivery network like Cloudflare. While I built Ymir to leverage CloudFront, Ymir also doesn’t force you to use it. It’s easy to change your project configuration so that you can use another content delivery network.
If you removed your CloudFront costs, you’d reduce your usage based costs by $0.26 per 1000 visits. That’s even more if you have a lot of media. So it’s a significant cost reduction change.
Spreading your fixed costs
The more projects you use Ymir with, the cheaper your fixed cost will get. That’s because Ymir makes it a breeze to use the same database server for multiple projects. So you can spread that $14/month cost over multiple projects. A small RDS instance can easily host dozens of WordPress sites.
The same goes with your Ymir cost. Ymir’s pricing has no usage based limitation. You pay $39 whether you’re using it for one project or dozens. So the more you use it for your projects, the cheaper it gets.
When does using Ymir for a single site start making sense?
Obviously, spreading your fixed cost doesn’t work if you only host a single site. So how much traffic do you need for Ymir to become competitive?
In general, your fixed costs won’t grow with your site traffic. This is especially true if you use CloudFront to do page caching. You can expect your small RDS database to be able to handle traffic well into million of visitors per month. (This is something I’ve load tested extensively.)
With that in mind, you’ll probably start seeing comparable pricing to managed hosting around 100,000 visits. Those plans cost are over $100/month. Meanwhile, you’d pay about $70 in usage based costs and $54 in fixed cost for a total of $124.
How much do you value peace of mind?
I really like this tweet by Jack Ellis. (The whole thread is worth reading!) There are advantages to using AWS Lambda that you can’t see by just analyzing server costs like we just did.
If you’re a server person, it’s easy to see how you can pay less for hosting your WordPress site. But there’s something fantastic about never having to worry about a server again. And that’s something that’s hard to put a price on.