Contact Us About Sponsorship

Questions about Micronaut Foundation sponsorship?

Please complete this form, and we’ll follow up with you shortly.

[hubspot type=form portal=4547412 id=a7b3ddfa-64b0-47fd-8358-45fa6a09456a]

Micronaut 2: AWS Lambda Functions

by Sergio Del Amo Caballero Tags:

Micronaut 2 includes many improvements to help you write Micronaut applications and serverless functions and deploy them to AWS Lambda.

Micronaut Application Types for AWS Lambda Functions

In Micronaut Launch, you can select the feature aws-lambda for applications of type Application or Serverless Function. Those application types have their CLI-equivalent commands.

Application Type CLI Command
Application create-app
Serverless Function create-function-app

AWS Lambda Considerations

To deploy an AWS Lambda function, you have to:

  • Select a runtime
  • Choose how your Lambda is triggered
  • Specify your Handler
  • Upload your code

The above decisions influence the type of Micronaut application you choose.

Select a Runtime

To deploy a Micronaut function to AWS Lambda, choose an AWS Lambda Runtime. For Micronaut functions, select a Java (8 or 11) or custom runtime. To deploy your Micronaut function as a GraalVM Native Image, select a custom runtime.

Select Java 11 Corretto Runtime

Select Custom Runtime

Application Type, Runtime, and Dependencies

Depending on your application type and runtime, you need different dependencies:

Application Type AWS Lambda Runtime ArtifactId
Application Java 8/11 micronaut-function-aws-api-proxy
Application GraalVM Native Image in a AWS Lambda Custom Runtime micronaut-function-aws-api-proxy, micronaut-function-aws-custom-runtime
Serverless Function Java 8/ 11 micronaut-function-aws
Serverless Function GraalVM Native Image in a AWS Lambda Custom Runtime micronaut-function-aws, micronaut-function-aws-custom-runtime

micronaut-function-aws-api-proxy has a transitive dependency to micronaut-function-aws.

The previous set of artifacts have a group id of io.micronaut.aws.

Micronaut CLI or Launch will include the necessary dependencies when you select the aws-lambda feature or both aws-lambda and graalvm features.

Choose How Your Lambda Is Triggered

AWS Lambda integrates with other AWS services to invoke functions. The Micronaut application type you select depends on the triggers you want to support. To respond to incoming HTTP requests (e.g. AWS Lambda Proxy integrations in API Gateway), you can choose either Application or Serverless Function. For other triggers, such as consuming events from a queue or running on a schedule, choose Serverless Function.

Application Type Trigger type
Application or Serverless Function HTTP requests to a single endpoint
Application HTTP requests to multiple endpoints
Serverless Function S3 events, events for a queue, schedule triggers etc.

On the one hand, if you need to support a single endpoint, a Serverless Function gives you a function with less code (which translates to a faster cold startup).

Functions written as an application of type Application allow you to code with a more familiar paradigm — classes annotated with @Controller. This is possible because, through the micronaut-function-aws-api-proxy dependency, Micronaut integrates with the AWS Serverless Java Container project.

Handlers

AWS Lambda Function Handler

Your Lambda function’s handler is the method in your function code that processes events. When your function is invoked, Lambda runs the handler method. When the handler exits or returns a response, it becomes available to handle another event.

The aws-lambda-java-core library defines two interfaces for handler methods. When coding your functions with Micronaut, you don’t implement those interfaces directly. Instead, you extend or use its Micronaut equivalents:

Application Type AWS Handler Interface Micronaut Handler Class
Serverless Function RequestHandler MicronautRequestHandler
Serverless Function RequestStreamHandler MicronautRequestStreamHandler
Application RequestStreamHandler < AwsProxyRequest , AwsProxyResponse > MicronautLambdaHandler

For functions of type Application, use the handler io.micronaut.function.aws.proxy.MicronautLambdaHandler.

To resolve that class, add the micronaut-function-aws-api-proxy dependency to your build.

For Serverless Functions, the decision to use one MicronautRequestHandler or MicronautRequestStreamHandler depends on how you want to handle the input and output types.

To resolve those classes, add the micronaut-function-aws dependency to your build.

With MicronautRequestHandler, it is expected that you supply generic types with the input and the output types. If you wish to work with raw streams, then subclass MicronautRequestStreamHandler instead.

Input / Output Types Handler
Supply generic types with the input and output Class which extends MicronautRequestHandler
Raw streams MicronautRequestStreamHandler

Cold Startups

Instances of Lambdas are added and removed dynamically.
When a new instance handles its first request, the response time increases, which is called a cold start. After that request is processed, the instance stays alive (≈10 m) to be reused for subsequent requests.

Lambdas execution has different phases (initialization, invocation …).

During the initialization phase:

  • AWS Lambda starts a JVM.
  • Java runtime loads and initializes handler class.
  • Lambda calls the handler method.

The intialization phase has access to more CPU; because of that, Micronaut starts the application context and eagerly inits singletons during the intialization of the handler class.

GraalVM and AWS Custom Runtimes

GraalVM is a universal virtual machine that allows you to compile Java programs to native executables.

The introduction of AWS Lambda custom runtimes enables cold startup improvements for Java applications running in AWS Lambda.

A runtime is a program that runs a Lambda function’s handler method when the function is invoked. You can include a runtime in your function’s deployment package in the form of an executable file named bootstrap.

Micronaut’s dependency micronaut-function-aws-custom-runtime eases the creation of AWS Lambda Custom runtime to execute a Micronaut function.

The main API you will interact with is AbstractMicronautLambdaRuntime. An abstract class that you can extend to create your custom runtime is mainClass. That class includes the necessary code to perform the Processing Tasks described in the Custom Runtime documentation.

When you generate a project with Micronaut CLI or Micronaut Launch with aws-lambda and graalvm features, the output includes the necessary files to generate a ZIP file to distribute your functions as a GraalVM Native Image executed from a AWS Lambda custom runtime.

Next Steps

We have written several step-by-step tutorials to get you started:

Application Type Runtime Tutorial
Application Java 11 Deploy a Micronaut application to AWS Lambda Java 11 Runtime JAVA KOTLIN GROOVY
Application GraalVM Native Image Custom Runtime Deploy a Micronaut application as a GraalVM Native Image to AWS Lambda JAVA KOTLIN
Serverless Function Java 11 Deploy a Serverless Micronaut function to AWS Lambda Java 11 Runtime JAVA KOTLIN GROOVY
Serverless Function GraalVM Native Image Custom Runtime Deploy a Serverless Micronaut function as a GraalVM Native Image to AWS Lambda JAVA

Check the Micronaut AWS documentation to learn more.