Lambda Provisioned Concurrency

Configuring your Datomic Ion Lambda with provisioned concurrency can alleviate Lambda cold-start issues when the Ion is infrequently invoked.

To configure provisioned concurrency for an ion lambda:

Example

The following example uses the aws-api to publish a new version of a lambda function, create an alias for that version, and configure provisioned concurrency for it. It should be run in an environment with proper AWS credentials to create and modify AWS lambda resources. The example can be run any time after an ion deploy to ensure that the latest lambda is published and configured with provisioned concurrency.

deps.edn:

{:deps {com.cognitect.aws/api       {:mvn/version "0.8.474"}
        com.cognitect.aws/endpoints {:mvn/version "1.1.11.842"}
        com.cognitect.aws/lambda    {:mvn/version "809.2.734.0"}}}
;; sample code

(require [cognitect.aws.client.api :as aws])

(defn aws-invoke!
  "Calls aws/invoke on the provided client and arg-map.
  Throws if the response map includes an anomaly, returns
  the map otherwise."
  [client arg-map]
  (let [resp (aws/invoke client arg-map)]
    (if (:cognitect.anomalies/category resp)
      (throw (ex-info "Anomaly returned from aws/invoke" resp))
      resp)))

(defn publish-and-set-concurrency!
  "Publishes latest lambda, updates alias, and
  sets provisioned concurrency.
  Requires the lambda name and an alias name as strings and
  the desired provisioned concurrency as an int.
  Returns the result map from final call to invoke
  operation for :PutProvisionedConcurrencyConfig"
  [{:keys [fn-name fn-alias concurrency]}]
  (let [lambda-client (aws/client {:api :lambda})
        publish-resp (aws-invoke! lambda-client {:op :PublishVersion
                                                 :request {:FunctionName fn-name}})
        alias-info (aws/invoke lambda-client {:op :GetAlias
                                              :request {:FunctionName fn-name
                                                        :Name fn-alias}})
        alias-resp (if (= (:cognitect.anomalies/category alias-info)
                          :cognitect.anomalies/not-found)
                     (aws-invoke! lambda-client {:op :CreateAlias
                                                 :request {:FunctionName fn-name
                                                           :Name fn-alias
                                                           :FunctionVersion (:Version publish-resp)}})
                     (aws-invoke! lambda-client {:op :UpdateAlias
                                                 :request {:FunctionName fn-name
                                                           :Name fn-alias
                                                           :FunctionVersion (:Version publish-resp)}}))]
    (aws-invoke! lambda-client {:op :PutProvisionedConcurrencyConfig
                                :request {:FunctionName fn-name
                                          :Qualifier fn-alias
                                          :ProvisionedConcurrentExecutions concurrency}})))

; Usage: (publish-and-set-concurrency! {:fn-name "my-lambda-name"
;                                       :fn-alias "my-alias"
;                                       :concurrency 1})

When using the newly configured lambda, for example as a target of API Gateway, specify the alias as the target:

my-lambda-name:my-alias

Note: AWS charges apply for lambda provisioned concurrency. See the lambda pricing guide for more information.