Unlocking the Power of Serverless: Deploying Lambdas with AWS CDK

Unlocking the Power of Serverless: Deploying Lambdas with AWS CDK

6 September 2023

Miguel Losa

Serverless computing is clearly on the rise. Many companies are starting to realise its potential when used correctly, but they don’t always know how to deploy these tools. In this blog, we’ll explore one of the most popular serverless solutions out there: AWS Lambda. We’ll show when and why to use Lambda functions, and how you can deploy them using Cloud Development Kit (CDK), the AWS Infrastructure as Code (IaC) tool. Let’s dive in!

What is AWS Lambda?

Amazon Web Services (AWS) Lambda is a serverless computing service that has revolutionised the way developers execute code. Thanks to AWS Lambda, you won’t have to worry about server provisioning and management anymore. You’ll get to focus on writing the logic of your application, while AWS handles the scaling, patching, and infrastructure management.

Lambda functions are event-driven, and can be triggered by various events. Data alterations in an Amazon S3 bucket, updates to a DynamoDB table, messages from Amazon Simple Notification Service (SNS), … you name it, Lambda can (probably) use it as a trigger. When triggered, Lambda will automatically provision the necessary resources, execute the code, and scale down when the function is idle. If it has been implemented correctly, this resource-efficient approach will help you to save costs, because you’ll no longer have to keep dormant services running.

Lambda is also flexible: it supports an array of popular programming languages, including Python, JavaScript, Java, C#, Ruby, PowerShell, and Go. This means that you’ll (probably) be able to use your language of choice when writing Lambda functions. Because it’s part of the AWS ecosystem, Lambda also offers seamless integrations with other AWS services. 

Finally, you can also add layers to implement any modules or libraries that you need for a Lambda function. This makes it possible to create generic layers, which you can then reuse in other functions. Thanks to these features, Lambda makes it a lot easier to build complex applications that require a serverless architecture.

What are some good use cases for AWS Lambda?

Let’s be clear from the get-go: Lambdas will only improve your environment when there is a need for them. The most important factor to consider is the average or maximum duration of a Lambda function: they are meant to be short-lived. Any functions that last longer than a minute – and even this is a bit of stretch – are probably better implemented in another way.

Another thing to keep in mind: Lambda functions should consist of one independent process. Don’t fall into the trap of making your function wait for other services! Avoid squeezing multiple processes into one Lambda. Instead, divide the processes and notify them using AWS’ Simple Queue Service (SQS) or Simple Notification Service (SNS). This is where those seamless integrations we mentioned earlier come in handy!

There are plenty of interesting use cases for serverless functions, but here are four options that should give you a good idea of where AWS Lambda truly shines:

  • Real-time file processing: you can use Lambda to process files as soon as they have been uploaded to an S3 bucket. Think of resizing images, extracting metadata, or custom processing.
  • Web and mobile backends: Lambda can also serve as the backend for web and mobile applications. It can handle tasks like user authentication, database operations, and business logic without the hassle of server management.
  • Scheduled tasks: Lambda lets you schedule tasks to run at a specific interval. We like to use it to generate reports, perform data backups, and periodically analyse data.
  • Serverless microservices: you can also use Lambda functions to build microservices that need to be deployed and scaled independently. By assigning a specific functionality to each function, it becomes much easier to maintain and update different components of your application architecture.

What is AWS CDK?

If you’ve been keeping an eye on our blogs, you’ll know that we’re currently trying out different tools to handle Infrastructure as Code (IaC). Like Terraform and Pulumi, AWS’s Cloud Development Kit (CDK) is a framework that lets you define cloud infrastructure with code. The similarities don’t end there: CDK also lets you write IaC in your programming language of choice, just like Pulumi, and it supports the creation of modular stacks.

The main difference is that CDK is tailor-made for AWS infrastructure: it translates your code to Cloud Assembly, so it can be deployed on AWS CloudFormation. On the other hand, Pulumi and Terraform are compatible with (nearly) all cloud providers and SaaS applications, but (presumably) less optimised for AWS.

If you already have CDK installed, you can initialise a new stack and AWS CDK will create a directory structure:

```
cdk init -a mydemoproject -l typescript

tree -L 2 --gitignore
.
├── README.md
├── bin
│   └── cdk-demo.ts
├── cdk.json
├── jest.config.js
├── lib
│   └── cdk-demo-stack.ts
├── package-lock.json
├── package.json
├── test
│   └── cdk-demo.test.ts
└── tsconfig.json
```

The only file that we’ll have to change is lib/cdk-demo-stack.ts, which contains the stack that we’re about to define.

We’ll demonstrate how to write code in AWS CDK using a simple TypeScript example, while accounting for possible expansions to the stack in the future through default properties. In this example, we’ll import an S3 bucket that contains a photo book, and use a Lambda function to resize any images that have been uploaded to it.

Importing the S3 bucket

 

```
import * as s3 from 'aws-cdk-lib/aws-s3';

// Default bucket props
const defaultS3Props = {
  publicReadAccess: false,
  blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
  removalPolicy: cdk.RemovalPolicy.RETAIN,
  accessControl: s3.BucketAccessControl.PRIVATE,
  objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
};

// S3 Bucket containing the photo book
const photoBookBucket = new s3.Bucket(this, 'PhotoBookBucket',
	{
		...defaultS3Props, 
		bucketName: 'mydemoproject-photobookbucket'
	}
);
```

Lambda function

 

```
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as lambdaEvents from 'aws-cdk-lib/aws-lambda-event-sources';

// Default lambda props
const defaultLambdaProps = {
  runtime: lambda.Runtime.NODEJS_16_X,
  timeout: cdk.Duration.minutes(1),
  handler: 'index.handler',
};

// Lambda function (e.g. for resizing images)
const resizeLambda = new lambda.Function(this, 'ResizeLambda', 
	{
	  ...defaultLambdaProps,
	  code: lambda.Code.fromAsset('lambda/resize.zip'),
	  functionName: 'mydemoproject-resizelambda',
	}
);

// Grant r/w permissions to lambda
photoBookBucket.grantReadWrite(resizeLambda);


// Add event source to lambda
resizeLambda.addEventSource(new lambdaEvents.S3EventSource(photoBookbucket, 
	{
		events: [ s3.EventType.OBJECT_CREATED ],
	}
));
```

Getting things running

To actually run these code snippets, paste them into the lib/cdk-demo-stack.ts file that we mentioned earlier. Place your imports at the top, and put your code inside the constructor of the stack.

Once you’ve logged into an AWS account with sufficient access privileges, you can deploy any changes to AWS using the cdk diff and cdk deploy commands.

We recommend always running the diff command, since it compares the current stack with the deployed stack. It will throw an error as soon as it can’t compile, spot circular dependencies, and identify other possible issues. If this completes successfully, you can rest assured that your deploy command will work as expected. Yep, it’s really that easy!

Conclusion

Lambda functions can be a convenient tool, but only when they are used where they actually provide a benefit. Don’t use them just to follow the latest trend, but check if you have a good use case for serverless computing. 

As far as AWS CDK is concerned: keep in mind that it is a specialised tool that only works with AWS infrastructure. If you’d like to use your IaC tool with other cloud platforms and SaaS applications, consider checking out Pulumi or Terraform instead. 

Finally, the example we used is just a straightforward stack: it has a simple Lambda function, no layers, and manual execution. To make things more interesting, you could implement its deployment in a CI/CD pipeline and make use of the generic layer functionality.

Want to learn more about serverless computing, IaC, and more? Follow our blog for high-level introductions and in-depth technical explanations of all things DevOps!

Related posts
No Comments

Sorry, the comment form is closed at this time.