Projecting events using AWS Lambda functions

How to create and deploy an AWS Lambda function to create projections/read models for your application

This guide will show you how to create and deploy an AWS Lambda function acting as a Serialized projector.

The function will automatically be called by the Serialized Event Engine whenever you store a new event. The call to the function will contain the event data, metadata and the current projection state (if any). The function will return a result that will be stored by Serialized as a projection.

In this example we will create a function that keeps track of how many times each user has logged in. We assume we have an aggregate called user and that an event called UserLoggedInEvent is emitted every time a user logs in. We will count every UserLoggedInEvent and increment a field called loginCount in our projection.

The project folder includes a template.yaml file. You can use this SAM file to deploy the project to AWS Lambda and Amazon API Gateway or test in local with SAM Local

Cloning the example project

git clone

Building the project

Using Maven, you can create an AWS Lambda-compatible jar file simply by running the maven package command from the project folder, event-projector-lambda

mvn clean package

[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Total time: X.XXX s
[INFO] Finished at: 2020-XX-XXTXX:XX:XX-XX:XX
[INFO] Final Memory: XXM/XXXM
[INFO] ------------------------------------------------------------------------

Testing the function locally

You can use AWS SAM Local to start the project.

First, install SAM local using npm or pip:


npm install -g aws-sam-local


pip install --user aws-sam-cli

Next, from the project root folder - where the template.yaml file is located - start the API with the SAM Local CLI.

sam local start-api --template template.yaml
Mounting EventProjectorLambdaFunction at{proxy+} [GET, DELETE, PUT, POST, HEAD, OPTIONS, PATCH]

Using a new shell, you can send a test payload to the API:

curl -i \
    --header "Content-Type: application/json" \
    --data '
      "metadata" : {
        "aggregateId": "a341b64c-b01f-43fb-907c-50c0067df672",
        "createdAt": 1587366182487,
        "updatedAt": 1587366182487
      "currentState": {},
      "event": {
        "eventId": "d710b9b1-063a-4b65-98be-0d46de443bdd",
        "eventType": "UserLoggedInEvent",
        "data": {
          "userId": "618f5a47-9d4c-4f42-9380-ca47c12087a1"

The jar file will now be automatically decompressed and executed by SAM. Note that this might take quite some time! The response should look like this:

    "updatedState": {
        "loginCount": 1

Try to change the POST above to include a currentState like this:

"currentState": {"loginCount": 99}

The response should now look like this:

    "updatedState": {
        "loginCount": 100

Deploying to AWS

You can use the AWS CLI to quickly deploy the application to AWS Lambda and Amazon API Gateway with your SAM template.

You will need an S3 bucket to store the artifacts for deployment.

aws s3api create-bucket --bucket event-projector-lambda --region eu-west-1 --create-bucket-configuration LocationConstraint=eu-west-1

Once you have created the S3 bucket, run the following command from the project's root folder - where the template.yaml file is located:

sam package --template-file template.yaml --output-template out.yaml --s3-bucket event-projector-lambda
Uploading to fa2xxxxxxxxxxxxxxxxxxxxxxxxa6359  9697552 / 9697552.0  (100.00%)
Successfully packaged artifacts and wrote output template to file out.yaml.

As the command output suggests, you can now use the cli to deploy the application.

sam deploy --template-file out.yaml --stack-name EventProjectorStack --capabilities CAPABILITY_IAM

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - EventProjectorStack

Once the application has been deployed, you can describe the stack to show the API endpoint that was created. The endpoint should be the EventProjectorLambdaApi key of the Outputs property:

aws cloudformation describe-stacks --stack-name EventProjectorStack --output json | grep "OutputValue"

         "OutputValue": ""

Now you can test the curl command above on your live lambda!

Using from Serialized

Create a projection definition referring to your remote function.

Example of a definition listening to events of type UserLoggedInEvent posted on an aggregate type called user.

curl -i \
  --header "Content-Type: application/json" \
  --header "Serialized-Access-Key: <YOUR_ACCESS_KEY>" \
  --header "Serialized-Secret-Access-Key: <YOUR_SECRET_ACCESS_KEY>" \
  --data '
    "projectionName": "login-count",
    "feedName": "user",
    "handlers": [
        "eventType": "UserLoggedInEvent",
        "functionUri": ""

The full documentation can be found here.

This example is based on Jersey Quick-start guide.