Hello,
I’m building a backend with AWS SAM and using Lambda functions (Node.js runtime with TypeScript) to process HTTP requests and send responses. The project integrates Prisma ORM to interact with an RDS MySQL database, and I’ve decided to place Prisma inside a Lambda layer for modularity and reusability across different functions.
Here’s a brief summary of my project setup:
Directory Structure:
ECOMMERCE-BACKEND-MCHOGAR
├── .aws-sam
├── src
│ ├── layers
│ ├── common
│ ├── prisma
│ │ ├── node_modules
│ │ ├── articulo.prisma
│ │ ├── jerarquia.prisma
│ │ ├── main.prisma
│ │ ├── proceso.prisma
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── prisma.d.ts
│ │ └── prismaClient.ts
│ ├── modules
│ │ └── Procesos
│ │ └── ProcesoSincronizacion
│ │ └── handlers
│ │ └── procesoDeSincronizacionConAikonArticulosInfoRelevanteHandler.ts
│ │ └── services
├── .gitignore
├── template.yaml
└── tsconfig.json
Relevant Template.yaml Excerpt:
Resources:
PrismaLayer:
Type: AWS::Serverless::LayerVersion
Properties:
Description: Prisma ORM for Lambda functions
ContentUri: ./src/layers/prisma
CompatibleRuntimes:
- nodejs20.x
LicenseInfo: 'MIT'
ProcesoDeSincronizacionConAikonArticulosInfoRelevanteFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./src/modules/Procesos/ProcesosSincronizacion/handlers
Handler: procesoDeSincronizacionConAikonArticulosInfoRelevanteHandler.handler
Runtime: nodejs20.x
Architectures:
- x86_64
Layers:
- !Ref PrismaLayer
Environment:
Variables:
DATABASE_URL: "mysql://<user>:<password>@<host>:<port>/<database>?connection_limit=1"
Events:
IniciarProcesoSincronizacionConAikonArticulosInfoRelevante:
Type: Api
Properties:
Path: /procesos/iniciar-proceso-sincronizacion-info-relevante
Method: get
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: true
EntryPoints:
- procesoDeSincronizacionConAikonArticulosInfoRelevanteHandler.ts
Code Snippet:
In `procesoDeSincronizacionConAikonArticulosInfoRelevanteHandler.ts:
import prisma from '/opt/prismaClient'; // Prisma client imported from layer
export const handler: APIGatewayProxyHandler = async (event) => {
const familia = await prisma.aikon_familia.findMany();
return {
statusCode: 200,
body: JSON.stringify({ familia }),
};
};
The Issue:
When I run npx prisma generate within the src/layers/prisma directory, Prisma works fine, but I am not getting TypeScript type suggestions when developing in my handler files, like procesoDeSincronizacionConAikonArticulosInfoRelevanteHandler.ts.
Since Prisma is in a Lambda Layer and included during runtime, it is not available during development, so TypeScript doesn’t recognize the Prisma types in my handlers.
Additionally, Prisma linting and TypeScript support are also needed in other parts of the project, such as in the services folder inside ProcesoSincronizacion. This folder contains TypeScript files where Prisma client will be used to build functions interacting with the database (e.g., using findMany(), create(), etc.).
I am using the following configuration in my tsconfig.json file:
"paths": {
"/opt/*": ["src/layers/prisma/*"] // Path alias for deployment environment
}
My Question:
What’s the best way to set up my project so I get full TypeScript support (types, autocompletion, linting) during development while still leveraging Lambda Layers for Prisma in production?
I want to continue using a Lambda Layer for Prisma to reduce duplication, but need proper TypeScript configuration to avoid losing the developer experience. Are there any best practices or solutions you would recommend to solve this issue?
Additional Context:
- I have Prisma schemas split across multiple files (main.prisma, articulo.prisma, etc.).
- I run npx prisma generate within the src/layers/prisma directory.
- I’m new to AWS SAM and Prisma, with about a month of experience in AWS services.
Any suggestions or best practices would be greatly appreciated!