Serverless is(n't) simple
At my last job, I built several serverless applications for clients on AWS. My development process towards the end looked drastically different from how I started, so I collected some of my lessons learned into this post.
This post focuses primarily on the experience of building serverless applications in AWS since that's the cloud I've worked in the most. The lessons learned should be portable to other public clouds, but the tools used will likely be different.
IaC all the things
Infrastructure as Code (IaC) is excellent for keeping your cloud environment under control. You can quickly see exactly what resources you have provisioned, along with all of their configurations. It's inherently portable to other applications too, needing only some changes to values (which should be extracted out to configuration variables).
CDK (Cloud Development Kit) is a great option for writing IaC that allows you to work in a programming language you're already familiar with like TypeScript or Java rather than working in a new language like Terraform's HCL or dealing with YAML/JSON templating in CloudFormation.
Terraform CDK is my preferred method of building infrastructure at the moment, but I don't care for Hashicorp's new "per resource per hour" billing scheme for the cloud state tracking/runner system offered. It can run for free in its open-source local mode, so if you find a good way to share state across engineers, it could work quite well.
AWS CDK is also an option, albeit a weaker one. Since it's a wrapper for CloudFormation at its core, you have to deal with CloudFormation's issues (rollbacks that can't be canceled but also take ages, poor drift detection).
Automate early
Setting up one serverless site isn't easy. On AWS, you need to figure out your configurations for S3, CloudFront (CDN), Cognito (auth), IAM, Lambda, Route53 (DNS), and likely at least one or two other services.
Automating serverless website creation, however, isn't much more complicated than making one serverless website. If you're planning on making several websites that use a similar stack, this is a great way to abstract away infrastructure and focus on developing your websites rather than managing servers.
If you used IaC, you can parameterize out resource names to accept variables at deployment time, along with other important values like domain names. If variables don't quite work (text in web templates, for example), you can use a bootstrapping system like Yeoman to interpolate values where necessary.
When I started making serverless websites, I manually copied over IaC and tweaked values as needed. After getting the hang of it (and remembering some gotchas like how to configure Google SSO), it would take ~4 hours hours to spin up a new website. Not terrible, not great. After adopting Yeoman and properly templating the code, it took as little as 10 minutes to spin up a new website that:
- Is hosted on our own domain with SSL.
- Requires authentication to access internal information, using the company's SSO or email/password with email verification1.
- Includes a basic page structure with authentication pages, public pages, and auth-required pages.
- Is logically isolated from other properties we host, in its own AWS account, simplifying permissions management and compliance.
- Costs < $5/mo to run for low-volume websites. I unfortunately don't have cost numbers for high volume serverless websites, but this cost comes from the single Route53 hosted zone for the website, along with the cost of S3 storage. Cost was typically < $1/mo for the first year because of the free tier.
If this level of automation doesn't seem well-suited to your usecase, it might not be worth it to pursue a serverless website. While one of the major benefits of serverless is its low cost and maintenance requirements, the cost of development can rapidly outpace your savings versus the cost of a small VPS with a comparatively simple configuration process.
Isolate your environments
One of the benefits of such a low-cost website is that it's similarly cheap to give each site its own infrastructure. There's no need for a shared database when you can run a couple DynamoDB tables for cheap/free in each account. This gives nice security benefits, including significantly easier management of IAM permissions so only relevant people can access the project's resources.
These low costs also make it less expensive to have more environments and less risky to make infrastructure changes. If you make a bad infrastructure change, you can catch it in beta before it affects any end-users.
This results in more resources, but your IaC should help keep it largely under control. Invest in pipelines to automate your deployment: this reduces risk from human error while reducing the time it takes to ship your code. Even if you're manually triggering deploys to production, the build system should handle the act of getting the code from your source repository into your cloud environment.
Is serverless worth it?
Planning to move cloud providers? Stay far away from serverless, at least until you get settled in on your new cloud. All the time you save at scale disappears if you have to migrate all this to another cloud. But most people probably won't need to do that (or are ok with keeping some services around in their old cloud).
If you're just planning to make the one site, it's probably not worth it to use serverless. You'll probably find yourself working around the limitations of the paradigm (such as the maximum response size from AWS Lambda), and at small scale the benefits of serverless are less pronounced.
I think serverless has a lot of benefits if you're running many distinct websites though. It's a system that reduces cost, encourages adopting best-practices like deployment automation, and simplifies maintaining your application.
1 Email verification doesn't technically work after 10 minutes, but the foundation is there. Because I had each site isolated to its own AWS account, each account needed to get the SES (Simple Email Service) identity approved for production usage by customer support. This process typically takes ~48 hours and 2 messages to support, but is only necessary when the site's ready for external users.