Serverless in general has been changing the way we architect and build software. More and more we see serverless applications moving beyond just Function as a Service (FaaS) and now involve stitching together a bunch of services (DynamoDB, S3, CloudFront, EventBridge, SQS, etc). The problem is the development and management of functions are different from the configuration and management of other services, but as we try to combine them to build a system or microservice we intuitively try and manage both aspects together.
Sam Kroonenburg describes this and how A Cloud Guru evolved their architecture to manage stateless and stateful stacks separately in a talk he gave at ServerlessConf NYC 2019
The idea for logically breaking up a microservice is to have multiple cloudformation stacks deployed separately within a microservice. You've got one for stateless resources like API Gateway and Lambda which you can just blow away at any time its just plumbing, its business logic. The other stack has state your DyanmoDB, your S3, which you have to be a lot more careful with. This reduces your blast radius because most deployments are only changing those stateless components, but if your state exists along side it in that thick microservice stack you have to worry about making changes, effects of a rollback, etc.
When I heard this it struck a cord because our team had more or less accidentally come up with a similar approach. For us we used Serverless Framework as our means of configuring, packaging, and deploying Lambda Functions and API Gateway. Whereas for the rest of the components CloudFront, ACM, Route53, S3, DynamoDB we used Terraform to manage.
Terraform allowed us to build off of modules others internally or in the opensource community created to simplify the configuration of these resources and gave an excellent ability to manage the state of the resources, detect drift, and more carefully apply changes. But when it came to API Gateway and Lambda Terraform was awful, API Gateway configuration is a nightmare and Terraform at least at the time didn't support packaging, deploying, or testing the functions themselves. To illustrate this Yan Cui in a blog post has a great example of just in terms of lines of code how much more there is to manage in Terraform vs Serverless Framework for just a single API Gateway event on a function.
So despite pressure to standardize on one framework it made sense for us to use Serverless Framework for the Lambda and API Gateway components of our applications while still using Terraform for the rest. But this use of two frameworks within a project might seem odd until you realize that...
managing stateful components and managing stateless components are two separate problems and it's okay to use separate tools for each problem.
Sam's talk helped me better articulate this point. Now if you are building serverless applications I would highly recommend trying to begin creating this logical separation within your serverless applications of stateful vs stateless components. If your like me you will find it ultimately increases your developers productivity, more easily use the right tool for the right job, and enable safer, more frequent deployments.
Now to hopefully give an idea of what this might look like for you I'll go through a couple examples.
The first example is using the native AWS tools CloudFormation and the Serverless Application Model (SAM). Here the A Cloud Guru architecture is actually a great example.
The only thing not noted explicitly on the slide is that here a developer working on the stateless stack could use SAM to simplify the creation of this stack. In addition using SAM would also do those things mentioned earlier like packaging code and dependencies for deployment, and allow you to do some local testing/debugging of your components.
With this approach the logical separation is handled through CloudFormation Stacks and variables can be shared between stacks by Exporting/Importing CloudFormation Outputs. This would be pretty much the textbook AWS implementation, where the only limitations are first that you have to be on AWS and limitations associated with CloudFormation.
To contrast that example there is the combination of Terraform for stateful components and Serverless Framework for the stateless components. Just to start for those not familiar here is a solid post outlining the differences between CloudFormation and Terraform, in addition to the post mentioned earlier by Yan Cui outlining the differences in some Lambda Deployment frameworks including SAM and Serverless. Terraform and Serverless Framework are both awesome opensource projects that are highly customizable and offer support for multi-cloud deployments.
If you go this route, Terraform does not use CloudFormation Stacks under the hood it manages its own state so in order to share variables between your stateful and stateless components I would recommend using SSM Parameters created in your Terraform and imported using Serverless Framework. The rest of the deployment for both Terraform and Serverless Framework becomes pretty standard using their respective CLIs and can be easily added to your CICD Pipeline. If you or your organization are already using Terraform for your Infrastructure as Code you might find this to be a natural combo for your serverless applications.
Again those examples are not at all inclusive of all possible solutions you could do Terraform & SAM, CloudFormation & Serverless Framework, or even mix in the CDK. But hopefully gives you some ideas how it might relate to your current setup for building serverless applications.
In conclusion I hope more people continue to build serverless applications that go beyond just functions, but in doing so make the choice to manage stateful and stateless components separately. If you have questions, comments, or found something I missed let me know in the comments or hit me up on twitter @aaron_osborne_.