AWS Lambda supports layers, so with a AWS provided JVM Runtime, we can put library dependencies in a layer.
The code in this repository shows how to split a JVM/Clojure project into
- Lambda with only the handler namespace AOT compiled
- Layer with the library dependencies
The AWS provided JVM Runtime looks up a handler class, with a specific event handler method, so we need to provide such a class.
The trick is to use requiring-resolve in the Lambda handler, to compile only the handler and not all application code, and to AOT only the handler namespace.
Postponing Clojure code to bytecode compilation to happen during the first event handler invocation would make the first invocation slow, but with AWS Lambda Snapstart, we can put the compilation to happen at the Snapstart invocation phase.
The code in this example makes the clojure compiler run at checkpoint creation time via runtime hook:
(defn -beforeCheckpoint [this context]
(println "Before checkpoint")
;; Do stuff here that would result in compiling the clojure application code, so the resulting process state can be checkpointed via Firecracker VM
((requiring-resolve 'layer-demo.core/get-clojure))
(println "Before checkpoint done"))
Compile the lamdba via
clj -T:build lambda
This produces target/lambda.jar
, which you can upload to a Lambda with JVM runtime.
Compile the layer via
clj -T:build layer
This produces target-layer/layer.zip
, which you can upload as a layer. Select the layer for the Lambda to use.