Deploying Prisma with AWS Lambda Layers in CDK

Alberta Motor Association
AMA Technology Blog
4 min readAug 2, 2022

Authors: Eric Bach, Winnie Ho

Prisma is a Node.js ORM that makes it easier for developers to build apps by abstracting many database-specific details with code. Unlike many other ORMs, it uses a schema-based definition to define the data models used in code to interact with the database engine. Along with TypeScript support, it offers easy-to-use migrations and cascading query operations. It is also actively maintained.

Depending on the runtimes, the Prisma and Prisma client package size can be huge. This poses a challenge with AWS Lambda since the Lambda deployment package size is limited to 50MB zipped or 250MB unzipped.

This article will highlight important points in designing a scalable serverless application that uses Prisma as an ORM in an AWS Lambda Layer that multiple AWS Lambda Functions can share.

Photo by Clark Van Der Beken on Unsplash

Project Overview

The starter serverless application project provides APIs as AWS Lambda function URLs that reference Prisma deployed in an AWS Lambda layer. This approach has two benefits:

  • It abstracts the Prisma Client in a dependency for all serverless functions.
  • It allows us to maintain a single copy of the Prisma schema within the Lambda layer. We can then update the schema in one place and have the changes reflected in all Lambdas.
Each Function URL has access to the Prisma Schema and Prisma Client.

The source code of this project is available here:
https://github.com/eric-bach/awesome-blog-samples/tree/main/prisma-layers

Project Setup

We start with the following folder structure:

src/
lambdas/
layers/

This project uses Amazon Aurora PostgreSQL as the database engine. But an RDS database would work too. Please refer to the stack definition in the repo to see how to create a database in CDK.

Prisma Lambda Layer Setup

The first step of setting up Prisma in our Lambda layer is to install the Prisma CLI as a development dependency:

cd src/layers
mkdir prisma && cd prisma
npm init -y
PRISMA_CLI_BINARY_TARGETS=rhel-openssl-1.0.x npm install prisma --save-dev
PRISMA_CLI_BINARY_TARGETS=rhel-openssl-1.0.x npm install @prisma/client

Next, we follow the documentation to initialize Prisma, connect the database, and create/migrate the database schema. Our schema looks like this:

⚠️ When installing Prisma dependencies and defining the database schema, we need to set the Prisma environment variable PRISMA_CLI_BINARY_TARGETS to rehl-openssl-1.0.x. Prisma CLI will then download the correct runtime binaries for AWS Lambda.

After we generate the Prisma Client again, we are ready to add the Lambda layer:

Bundling the Prisma Lambda Layer in CDK

At the beginning of this blog post, we mentioned the size limits in Lambda deployment packages. To work around the limitations, we need to remove the Prisma Client binaries that are not relevant to the Lambda runtime environment when we bundle the layer in CDK:

⚠️ Our team had to remove binaries for Darwin, Debian, and Windows because we are a cross-platform team and use GitHub Actions to automate our CI/CD workflows.

Lambda Setup

Before we create the Lambda, let’s update tsconfig.json:

During the init phase of the Lambda lifecycle, the Lambda service extracts the layer contents into the /opt directory when setting up the execution environment for the function. The code of our Lambda layer will be available at /opt/client. To make that work locally, we need to add baseUrl and paths to re-map the imports to the actual local lookup locations.

Here is the code for the Lambda function that calls the createUser method imported from the Lambda layer:

We import createUser in the Prisma Lambda layer from /opt/client, the location where the Lambda service extracts the layer code to.

Finally, we add the Lambda, apply the layer we created earlier, and add the function URL in CDK:

Now we can apply the layer to all future Lambda functions, and they would automatically have access to the Prisma Client and all data access methods.

Summary

Lambda layers allow us to share libraries and dependencies with our Lambda functions conveniently. By centrally managing the Prisma Client, the Prisma schema, and data access methods in a Lambda layer, we have a scalable way to deliver new functionality in a serverless application.

References

--

--