Serverless guiding principles deep dive: #1 - Use a framework
There are seven guiding principles to serverless systems which, if applied, help your team and company execute more effectively in serverless technologies. In my original article I summarized all seven, but left it at the 10,000 ft perspective. In this article I will go over the first of the seven guiding principles, providing even more context for the principle and its resulting impacts.
The first principle focuses in on using a serverless framework. In this article we'll explore what serverless frameworks will do for you, if it's practical to use a cross cloud provider approach, impacts on development teams, how to split up responsibilities between application teams and infrastructure focused groups, and finally what happens when you don't use a framework.
Why not just any framework?
There are many frameworks out there for AWS, Azure and even cross cloud infrastructure. A lot of these frameworks move infrastructure into code, allowing iterative improvements which your CI/CD system can deploy across environments and accounts, as well as rolled back to a previous state easily. They address the problem of most standard networking in the cloud is very similar, so why not make a common language for it that can then be applied across cloud environments.
Serverless adds a nuance here that typical frameworks have a problem comparing to. First is that serverless systems take advantage of almost 100% platform native capabilities. The capabilities rely on core concepts built into each platform's approach at a fairly low level.
This example looks at an AWS Serverless API which is used to connect to DynamoDB. For AWS there are a lot of components that need to be tied together in order to get basic serverless systems operational, and not all of them are obvious.
An example of this is API Gateway, which requires the following components:
This is assuming a simple scenario. On top of this, the serverless code needs to be compiled, packaged, referenced in the cloudformation at its destination in S3, uploaded, the cloudformation change set created and the deployment kicked off. While compilation and creating a change set are optional steps, there's quite a bit of orchestrating activities that need to occur. With effort It can be accomplished, but you start working against the tools rather than with them.
If you were to take the same scenario on another cloud provider like Google Cloud. The immediate problem you run into is there are a lot of differences from the format the data sent to the developers code, to the interfaces, to data interactions/limitations which the code needs to be aware of. Since serverless functions are small, you'll most likely have to re-write your function code for each cloud platform you wanted to replicate it to. The typical cost for serverless systems is so low that there's very little benefit to increasing its complexity for multiple cloud platforms.
There is an enormous benefit to leveraging a provider native framework for your development teams. Here is the same example as above with the AWS SAM framework.
The framework still creates all the other components AWS needs, but simplifies the infrastructure as code and reduces the complexity for the development team. The result is that most developer with a bit of hands on experience can easily understand the infrastructure components better, resulting in the ability to act more independently and effectively when extending the system.
This approach also reduces the effort to build and maintain your serverless architectures. Frameworks also provide a level of abstraction from the detailed resource perspective but still supply native integration to the provider. The added benefit here is that integrating with native services becomes easier, as well as staying up to date with the latest capabilities your cloud provider is offering.
Developers have to do what?
One area of improvement for serverless is the development experience. Serverless is already a very abstract concept from traditional development practices. Throw in that the execution environment is in a container which leverages events rather than direct API integrations, then add cloud native authentication on a developer machine which is not cloud native and you start to get the picture. For developers, it's not easy to simulate and debug serverless systems if they don't have local debugging capabilities readily available.
Where developers are coming from
The development experience for traditional systems went through these same challenges early on, but have the benefit of having decades of tools built to solve these challenges. If a developer wants to develop and test an API, for example, the development tools will fire up mini-server on their machines. This mini-server opens up debug ports and the developers IDE will automatically connect to it. The mini-server will then leverage the user's authentication authority and allow for more traditional interactions with the network around the developer's machine.
What's different about serverless
In serverless the environment the developer's code is running in a container which is managed and maintained by your cloud platform provider. Permissions for the developer's code is provided by cloud native roles and potentially company managed networking constructs like VPCs, with specific access to resources for the serverless code using VPC native concepts. This all leads to significant challenges as container development is just becoming common practice but developers don't have a lot of experience with the technology still.
Running the serverless environment on a developer's computer is possible, but it requires a significant amount of knowledge on how containers work, how to pull down and setup the provider's specific container and various other tasks.
How frameworks help
Serverless frameworks step in here to fill in the gap, at least a good bit of it. The frameworks offer your developers the ability to run their code in a simulated serverless environment, including the ability to debug in that environment. It doesn't hook directly into the event architecture of your cloud provider yet, but it allows developers to leverage events they captured from native components and re-run them on their local machine. Recently AWS SAM has made it possible for developers to host a simulated Api Gateway on their machine, allowing interactions with serverless components to be even easier.
Other companies like Stackery are also innovating in this space. Stackery extends the AWS SAM development experience by adding replication of cloud event invocations on the local developer's machine and role specific permissions for the function being developed rather than the developer's permissions.
There is still more that can be done in this space but the upside of serverless overshadows these problems.
Can there be a middle ground?
What happens when your infrastructure and traditional solution architecture team wants to use a cross platform toolset, while your developers would benefit from serverless frameworks? The good news here is that it's not a one size fits all problem. Cloud platforms offer a variety of ways to pass configurations from more traditional data and service layers to serverless components. It's even recommended by AWS to separate your AWS stacks into modular components layers in their article on "8 best practices when automating your deployments with AWS Cloudformation".
If you're bought into cross cloud, consider leveraging serverless frameworks for your development team's processing and workflow components, while leveraging cross cloud frameworks for database, cloud networking, access and various other aspects. I recommend this split approach even when working on the same cloud platform, as it allows the separation of roles within the organization and allows compute components to have capabilities like Blue/Green, re-baselining, and simplified compliance efforts.
What happens when a framework is not used?
When I first started out, I started without a serverless framework, writing cloudformation by hand and struggling all the while. I was shocked by how much effort when into defining serverless infrastructure, and how many components were hidden under the covers that I never knew existed. I still got code into production, but it took a lot of time and caused a lot of frustration.
So what happens when your team doesn't use a serverless framework and falls back on older habits or older approaches? The first repercussion is that your team starts using the built in development environments in your provider's cloud platform, saving code there then executing it. On its face this is probably the simplist way to get started as a developer.
In practical experience here are a few repercussions:
Code changes don't get checked in fully to your source control (some but not all)
The code is often in a state when a new developer can't create a new environment for themselves
Releases to higher environments are fraught with errors
The team is spending a lot of time trying to figure out where they put the code that was missed and why it didn't get checked into source control
I had an experience where we were releasing our first serverless component to a test environment and a critical function was overlooked, being manually created but not added to the cloudformation template. After the deployment completed, the new system just quietly did nothing as we scrambled to figure out why.
Serverless frameworks will help the development team's experience by making it easier to define new resources to develop on the developer's machine. The result is that it improves the confidence that what is checked into source control will work in higher environments without missing pieces.
Writing serverless systems can be life changing for many developers. I've had developers who transitioned to serverless and stated that the company could send them back to their old team but they would do serverless work there as well. The simplicity of the code, the reduction of standard retries and error checking which is just handled by the cloud platform is amazing. Without a framework, all of those benefits can get hidden behind instability, effort to perform basic development operations and lack of common development experiences. Using a framework helps all of those areas while abstracting away the detailed aspects of integrations with cloud native components, which empowers your development team and increases velocity of features going to production.