One Package Multiple Lambdas with Quarkus Lambda

The Problem

There were only one hiccup, Quarkus allows you to package multiple Lambdas in the same java/module but only one can be active at the time. to receive Lambda events. Meaning that if you want to use the same native-image as the binary of multiple Lambdas you will either need to compile the module for each Lambda you would like to use or simply break down your module in multiple ones with only one Lambda in each one of them.

The (a) Solution

Quarkus allows you to include the scripts which bootstraps the native image binary, it is really well documented here: Custom bootstrap script. All you need to do is to create a file named bootstrap inside src/main/zip.native. Here is the content of my bootstrap script:

#!/usr/bin/env bash

./runner -Dquarkus.lambda.handler=$HANDLER_NAME
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
Token Payment

Parameters:
DeploymentEnvironment:
Type: String
Default: "develop"
AccountingTableName:
Type: String
Default: ""
AccountingServiceIndex:
Type: String
Default: ""
ReportingTableName:
Type: String
Default: ""
DomainSslCertificateArn:
Type: String
Default: ""
DomainName:
Type: String
Default: ""
CompilationType:
Type: String
Default: "aot"

Mappings:
HandlerMap:
jit:
AuthenticatingHandler: com.payment.authenticating.LambdaHandler::handleRequest
AccountingHandler: com.payment.accounting.LambdaHandler::handleRequest
ReportingHandler: com.payment.reporting.LambdaHandler::handleRequest
PricingHandler: com.payment.pricing.LambdaHandler::handleRequest
Runtime: java11
CodeUri: infrastructure
AreSignalHandlersDisabled: false
aot:
AuthenticatingHandler: not.used.in.provided.runtime
AccountingHandler: not.used.in.provided.runtime
ReportingHandler: not.used.in.provided.runtime
PricingHandler: not.used.in.provided.runtime
Runtime: provided
CodeUri: infrastructure/build/function.zip
AreSignalHandlersDisabled: true

Globals:
Function:
Runtime: !FindInMap [ HandlerMap, !Ref CompilationType, Runtime ]
MemorySize: 4096
Timeout: 20
AutoPublishAlias: !Ref DeploymentEnvironment
Environment:
Variables:
DISABLE_SIGNAL_HANDLERS: !FindInMap [ HandlerMap, !Ref CompilationType, AreSignalHandlersDisabled ]


Resources:
TokenPaymentHttpApi:
Type: AWS::Serverless::HttpApi
Properties:
Domain:
CertificateArn: !Ref DomainSslCertificateArn
DomainName: !Ref DomainName
Auth:
Authorizers:
BearerTokenLambdaAuthorizer:
AuthorizerPayloadFormatVersion: 2.0
EnableSimpleResponses: True
FunctionArn: !GetAtt BearerTokenAuthenticationFunction.Arn
Identity:
Headers:
- Authorization
DefaultAuthorizer: BearerTokenLambdaAuthorizer


BearerTokenAuthenticationFunction:
Type: AWS::Serverless::Function
Properties:
Handler: !FindInMap [ HandlerMap, !Ref CompilationType, AuthenticatingHandler ]
CodeUri: !FindInMap [ HandlerMap, !Ref CompilationType, CodeUri ]
Environment:
Variables:
HANDLER_NAME: authenticating


GetProcessingPriceFunction:
Type: AWS::Serverless::Function
Properties:
Handler: !FindInMap [ HandlerMap, !Ref CompilationType, PricingHandler ]
CodeUri: !FindInMap [ HandlerMap, !Ref CompilationType, CodeUri ]
Events:
GetProcessingPrice:
Type: HttpApi
Properties:
ApiId: !Ref TokenPaymentHttpApi
Path: /pricing/v1/token/{processing_price}/{number_of_units}
Method: GET
Environment:
Variables:
HANDLER_NAME: pricing


PayBillFunction:
Type: AWS::Serverless::Function
Properties:
Handler: !FindInMap [ HandlerMap, !Ref CompilationType, AccountingHandler ]
CodeUri: !FindInMap [ HandlerMap, !Ref CompilationType, CodeUri ]
Events:
PayBill:
Type: HttpApi
Properties:
ApiId: !Ref TokenPaymentHttpApi
Path: /accounting/v1/bill/{bill_id}/pay
Method: PATCH
Environment:
Variables:
HANDLER_NAME: accounting

ReportProcessingServiceFunction:
Type: AWS::Serverless::Function
Properties:
Handler: !FindInMap [ HandlerMap, !Ref CompilationType, ReportingHandler ]
CodeUri: !FindInMap [ HandlerMap, !Ref CompilationType, CodeUri ]
Events:
ReportProcessing:
Type: HttpApi
Properties:
ApiId: !Ref TokenPaymentHttpApi
Path: /reporting/v1/processing
Method: POST
Environment:
Variables:
HANDLER_NAME: reporting

Conclusion

I was able thanks to Quarkus to generate a native image for Rapid Linux using GraalVM for my four Lambdas and reduce the response time of my cold starts + first invocation by a up to a factor of 10.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Hamady C.

Hamady C.

Passionate Coder — Servant Leader