Blog series: from zero to hero! Part 2: Serverless backend api on AWS for blog website.

Depascale Matteo
8 min readJan 17, 2023

--

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

Photo by Gabriel Heinzer on Unsplash

The needs

There are a few points we need to mention:

  1. Lambda code must reside outside of infrastructure folder structure;
  2. There will be some common functionality shared between every function;
  3. Api resources should not be placed within the api gateway stack;
  4. 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;
  5. 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;
  6. 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.

Project structure
Figure 1: project structure.

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:

Result of running serverless offline
Figure 2: local api gateway.

then we can call api gateway resources like so:

Local api gateway testing with postman
Figure 3: local api gateway testing with postman.

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:

  1. Lambda cold start & miss from Cloudfront: 800-900msā±ļø
  2. Miss from Cloudfront: 200-250ms
  3. 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:

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/.

--

--

Depascale Matteo

Hi I'm MatteošŸ‘‹! Iā€™m an AWS Cloud Engineer and AWS Community Builder passionate about Serverless on AWS. Follow me https://www.linkedin.com/in/matteo-depascale/