Blog series: from zero to hero! Part 2: Serverless backend api on AWS for blog website.
Developing the core business of a blog website using Typescript and NodeJS 18 with AWS Lambda functions š. Letās try to make it developer friendly and locally testable shall we?
ā ļø Hey! This blog post was initially published on my own blog. Check it out from the source: https://cloudnature.net/blog/blog-series-from-zero-to-hero-part-2-serverless-backend-api-on-aws-for-blog-website
The needs
There are a few points we need to mention:
- Lambda code must reside outside of infrastructure folder structure;
- There will be some common functionality shared between every function;
- Api resources should not be placed within the api gateway stack;
- Our time to market is tight, we need developers (for this project, developers = me, but thatās a secretš¤«) to be freed from every type of burden outside developing code;
- We donāt want to introduce too many new technologies, right now we are using CDK with Typescript, letās keep it or use some similar tools;
- It must be locally testable.
Well, we are ready! Buckle up, itās a bumpy road š£ļø. Itās even more rough if you didnāt read the first part, check it out š Iāll wait for you
Perfect by now I assume you are up to date and know the infrastructure.
The process
We will go through every step we need to take to decide which is the right approach for our use case, if you are not interested in it you can skip to the final part, no hard feelings about itš.
First we need to decide which is the right tool for Infrastructure as code to use, then we must find the most suitable folder structure for our use case.
Which tool for infrastructure as code is better?
The one you are comfortable with!
That was easy, Iām not trying to clickbaitš£. As far as our use case concerns I did a few tries with the following tools:
- Serverless Framework
- AWS SAM
- AWS CDK
- Terraform
This is just an opinionated pros and cons focused on my own blog, which means it doesnāt have 200 api. If this gets enough attention I may write an article just about IaC tools pros and cons.
Letās see one by one š and compare them based on our use case and technology stack.
AWS SAM
Itās really great and connects natively with lots of AWS services. The thing I like most is its ability to be able to specify nested stack but as of this moment you cannot reference the same api gateway id, which means every nested stack has itās own api gateway url.
As per the ability to test locally, AWS SAM does a great work, it use a docker container to start the api gateway locally or invoke a single lambda function. Itās a little bit slow compared to other tools but thatās because you are testing on the same environment as the one you will use on AWS.
You can read about AWS SAM right here š
Terraform
Love this tool but I would have to create all the serverless infrastructure by myself, besides it has its own language so Iām not eager to introduce a new language to the project.
As far as I know you cannot test it locally, you would need to invoke every lambda with Node to test them.
AWS CDK
It would be great to use this tool because we are already using it, but I donāt think it fits our needs on the long run. I do not imagine having 200 api with CDK.
You cannot test your api locally but with a little bit of help from AWS SAM you are able to test locally your api and also invoke the single function.
I did try out CDK + SAM but I was not comfortable with how the the project structure turns out. Moreover Iāve opened a bug to aws-lambda-nodejs because it doesnāt work with nested stack, you can read about it here https://github.com/aws/aws-cdk/issues/23181.
Serverless Framework
I love this tool, Iāve used it for a few years and I couldnāt not give it a shot. Itās fast and simple to use, just a few lines of typescript and you can create the serverless infrastructure you need, you can also write your own CloudFormation code. Moreover the community is great and there are a lot of plugins you can use, this helps when something is not natively supported by the framework.
You also can test locally and itās lightning fast which is something I personally love about this tool.
You can find more info about Serverless Framework right here š
(no itās not sponsored, Serverless build a wonderful tool š)
Infrastructure as Code next steps
As you probably already know I opted for AWS CDK + Serverless Framework right after trying AWS CDK + AWS SAM and finding out I was not satisfied with the resultš¤¦āāļø.
Now that we have sorted this debate out we can start building with Serverless Frameworkš·!
AWS CDK combined with Serverless Framework
Well first thing first we need to install Serverless Framework, which is really easy:
npm install -g serverless
and then start with the template for typescript and Node.js
serverless create --template aws-nodejs-typescript
Perfect, we need to install the packages and we are ready to roll.
Project structure
The following picture shows the final folder structure and their files.
serverless.ts
This file contains our api gateway configuration and itās resources, as well as plugins and their configuration. Itās really handy, letās see a few points worth mentioning:
here we are installing serverless-esbuild plugin: within custom object we have esbuild configuration. We use esbuild to have better performance as building time as well as package size, if you are interested in knowing how to improve your lambda function below here there are 15 tips and tricksš
We are also installing serverless-offline which enables us to use the command <serverless offline> and test our infrastructure locally.
Then we start defining api configuration, we need to import resources created through AWS CDK such as:
- api gateway and its api key;
- cognito api authorizer;
- resources id and arn as custom object.
Custom parameters
I didnāt want to put there hardcoded values, so I imported them from AWS CDK created stacks and also from the AWS Parameter Store. Now itās much cleaner š
Create post api
First we need to define the post object, which will be used as validator directly with api gateway:
for now I think we can rock with this configuration, we will spice things up when weāll introduce SEO š„.
Then we need to define our api, which means we need to specify how api gateway integrates with lambda function.
As you can see in a few lines we did set up:
- cors;
- authorizer;
- lambda function;
- api definition;
- api key;
- method definition.
Thatās what I really like about this tool (as well as AWS SAM), in a few lines you have everything put in place for you š.
Finally we obviously need logics, letās create a simple create api:
there are a few things worth mentioning:
- I built my own function to handle connection with DynamoDB;
- we are replacing title and content to prevent html and XSS injection, you never know š;
- I built a middleware which does standard operations for every lambda function (like printing events or parsing body to JSON) and then return the api gataway response with the status code we specify.
I could have used middy for this but I want to try it out sometime in the near future; - I built my own logger which is absolutely the effortless logger ever existed š.
ā ļøNote: I wonāt go into details for every single api, if you are interested in them you can find the GitHub repository down below.
Cache invalidation
As you know we also have a DynamoDB stream that invokes a lambda function which invalidates Cloudfront cache. How can we trigger a lambda function with DynamoDB? The answer is in less than 20 lines of code:
and the lambda logic is event easier:
It invalidates Cloudfront cache, doing so the api gateway shows new posts or changes to old posts.
Local testing
This is the part I was eager to show you! We just need to run:
serverless offline
and our local api gateway is listening:
then we can call api gateway resources like so:
Really useful and fast to set up, this is why I love this tool so much āØ.
Performance
Letās see how our serverless infrastructure actually performs šļø. Iāll just post the result, our test consists in invoking Cloudfront and list the first 20 blog posts:
- Lambda cold start & miss from Cloudfront: 800-900msā±ļø
- Miss from Cloudfront: 200-250ms
- Hit from Cloudfront: 20ā40msššš
We have almost one second of latency the first time we invoke Cloudfront, but earlier we set up a caching policy with minimum time to live of 14 days, which means we will receive a cache hit for 2 long weeks. Iām really satisfied with those number because running on serverless and having our blog loads in less then 50ms is an absolute win.
Conclusion
In this posts we learnt how to create a serverless backend supporting AWS CDK, we built it with Serverless Framework with Typescript and we were able to test it out locally.
You can find the project here https://github.com/Depaa/website-blog-part2š
This series is literally a journey to production, hence you will see a lot of blog posts, here is a list Iāll try to keep updated:
- ā Serverless infrastructure on AWS for blog website;
- ā Backend Api on AWS for blog website;
- ā Building a high performing static backoffice on AWS with SvelteKit;
- ā Frontend users website for reading blog posts;
- SEO tweaks for blog website;
- Analytics and tracking views on our blog website;
- Infrastructure monitoring and alerting to the blog;
- Going live with the blog;
- CICD pipelines for the blog;
- Disaster recovery, RTO and RPO. Going multiregion with serverless;
- ā¦ you see, there are a lot planned, and if you want to add more points just DM me or comment right below.
Thank you so much for reading! š I will keep posting different AWS architecture from time to time so follow me on Medium āØ or LinkedIn š https://www.linkedin.com/in/matteo-depascale/.