Kicking Complexity to the Curb with AWS SAM

The introduction of serverless development represents a shift in the fundamental technologies that drive web development. Moving from mono-API or microservice architectures to a serverless architecture is a critical step in realizing the benefits of this new paradigm; it can also be a problem-space in and of itself. As Badri Janakiraman observed on Martin Fowler’s website on serverless tech: 

“The conceptual overhead of splitting a single application into something that [is] woven from a fabric of services is significant and increases with the number and variety of services used.” 

Where before you were presented with a coherent application unit, in a serverless model, your application’s visibility and maintainability will at first seem chaotic and complex simply due to the nature of serverless technology. 

AWS SAM (Serverless Application Model) addresses this problem of application cohesiveness at the macro level, providing you with both a framework to guide your development and command line tools to facilitate it. In this post, we’ll discuss serverless development using AWS SAM. We’ll highlight the challenges it solves in serverless development and provide tips and tricks on getting the most out of this powerful tool.

A Quick Review of Serverless Development

Serverless development is an evolution of two distinct patterns: containerization (i.e., Docker) and Infrastructure-as-a-Service software (i.e., EC2). The focus in serverless development is on breaking your application down into component functions by leveraging dynamic containers that are spun up on-demand. These are managed by a transparent platform, which handles instantiating, running, and tearing down your functions.

Serverless applications, despite the implication of their name, still require servers to run. The servers in these applications, however, are ephemeral containers that are created on-demand when the functionality of your application is invoked. Serverless applications greatly reduce the amount of infrastructure that needs to be developed, letting you deliver code and release features more quickly in several different realms. 

By removing the burden of handling infrastructure, serverless development also allows you to focus your resources on the parts of your application that matter the most to your users.

If you’re looking for some more in-depth content with a focus on serverless technology itself, refer to our earlier post, Serverless for Humans.

Serverless Development in AWS Using AWS Lambda

In AWS, serverless development is achieved using AWS Lambda functions–individual pieces of executable code, akin to scripts that are run on-demand. These code objects are individually executable, as they are built within the framework provided by AWS Lambda, a standardized entry point that each Lambda function can share in common. 

AWS Lambda allows you to focus on the individual elements of your application at the function level and does not speak to–nor account for–an overarching system design. This lends itself well to intermittent workloads, such as batch processing jobs or functions called in response to user behavior. Thus, AWS Lambda often works best in event-driven environments and transformative workloads, although these are not the only ways you can use it.

AWS Lambda has a few competitors, including Google Cloud Functions and Microsoft Azure Functions. Each provider, including AWS Lambda, has its own strengths and weaknesses, as any cursory review of popular blog posts. However, it is important to determine if the challenges and benefits presented by each ecosystem are worth the effort. For example, we’ve done a comparison between AWS Lambda Functions and Microsoft Azure Functions, which provides valuable insight into the pros and cons of each platform. 

Once you move beyond simple serverless functions, you can build truly powerful serverless ecosystems based on tools like AWS Fargate and Google Cloud Run to match your feature pipeline.

The Challenges of Maintaining Serverless Applications

Significant shifts in technology often come with new challenges to surmount. AWS Lambda is no exception here. Given how large groups of AWS Lambda functions can get, there are a number of problems that can quickly arise in your codebase as it grows. The ones we will cover are code duplication, complexity growth, and observability.

Code Duplication

As each function is deployed to production, it cannot share code; each function needs to have its own copy of every library that your code depends upon. This means multiple copies of the same libraries, multiple deployments when shared libraries are updated, and other anti-patterns that emerge out of necessity.

Increased Complexity

The issue of sharing code is perhaps small, given that command line tools can go a long way towards generating these shared files automatically. But the growth of complexity makes this more troublesome. With the move from a singular application architecture to a collection of disparate functions, complexity grows geometrically at the rate of connections between your functions themselves. This makes following the control flow of your application a challenge without an early focus on distributed tracing in your development. Furthermore, this complexity grows in a decentralized manner, as without an overarching design, your system simply exists as a collection of functions that duplicate both code and configuration.

Observability

Growth in complexity also drives a decline in the observability of your application. Observability in traditional applications is a complex space, and serverless architectures compound this problem twofold. Breaking a traditional application apart into serverless functions means that there are more touchpoints to monitor, and as the containers for each function are destroyed after usage, post-fact analysis of failures can be challenging–if not impossible–in some scenarios.

AWS SAM to the Rescue

Amazon Web Services, in recognition of the growing complexity in serverless development patterns, has answered this industry need with its Serverless Application Model, or AWS SAM. This model presents a framework within which serverless developers can operate. It uses configuration files and command line tools to ease the process of developing and maintaining serverless applications, providing a cohesive view of the application as a whole.

AWS SAM brings all of the configurations needed to build, run, and deploy your serverless applications under one roof. It uses a templating system and configuration files, transparently managing the complexity of AWS Lambda code deployment. This model provides a comprehensive set of CLI tools that can drive your application, offers easy configuration for the AWS Services that drive your Lambda functions, and more. This allows you to create reproducible and reducible patterns, building components that are part of a whole rather than disparate functions operating in isolation.

Figure 1: AWS AMS (Source: AWS)

Benefits of AWS SAM

AWS SAM is a collection of command line tools, frameworks, best practices, and development patterns that bring many powerful benefits to serverless application development teams. The first of these is the powerful out-of-the-box CLI. 

The AWS SAM CLI provides tools to invoke your functions locally, establish an API to test specific events, build your functions, and deploy your functions to AWS Lambda–all with the associated updates to your application’s event triggers. 

The screen below shows a brief overview of everything you can accomplish through the command-line interface:

Figure 2: AWS SAM CLI

This is driven by a powerful templating system, reducing the overall complexity of configuring Lambda functions and the triggers that drive them. These tools are also UNIX-compliant, meaning that they can be integrated into your CI/CD pipeline of choice.

In addition to the deployment tools, AWS SAM provides a test harness that allows you to easily test and debug your functions locally. This can be done through the traditional execution of unit testing, establishing a local API to respond to API events, or anything in-between using local Docker containers designed to mimic the Lambda execution environment as closely as possible. It’s also fully integrated with the AWS SAM CLI:

Figure 3: Build process and command for test harness

Finally, AWS SAM employs best practices to encourage code organization. While the core issue of code duplication is inherent to the design of AWS Lambda and cannot presently be easily circumvented, AWS SAM gives you a framework in which to iterate these shared dependencies. Once your changes have been made, AWS SAM guides you in ensuring that all of the code dependent on your changes is deployed, instead of requiring a manual process of deploying each dependent function individually.

Conclusion

Serverless development is an exciting space due to its dynamic pace of innovation. However, this fast pace can often get ahead of the platforms themselves, leading to inefficiency in the development and maintenance of serverless applications. 

AWS SAM is a powerful tool for managing the configuration complexity of serverless applications and reducing the complexity of serverless apps. It achieves this by providing a coherent model of serverless application design and development, giving you the tools you need to deploy and maintain your serverless applications with confidence.

Check back for more articles like this, or if you’re a tech expert who wants to contribute your expertise, reach out to us and let us know!

Related posts