Hi! We are currently developing a backend in Apoll...
# orm-help
o
Hi! We are currently developing a backend in Apollo+GraphQL+Prisma+Typescript with a Postgres DB. We are now looking for a way to deploy it to AWS, but we dont know what best practice is. From what we understand, prisma is too large to fit in AWS Lambda. Does anyone have experience or tips to share on how to get such a backend into production on AWS? Thanks! 🙂
m
HI Oliver, I did this as recently as this very week with AWS CDK. In my case, I also had a dependency on type-graph which disallowed the use of the built-in NodeJS lambda support. My setup is a bit too integrated with a larger project, but here are some things that may help. So the biggest issue is that there are a lot of big binaries thrown around in the prisma packages, the binaries are somewhere in the generation flow also copied and replicated further, making the prisma packages take about 350 mb of space just in binaries(!!!) while they only need about 40mb for the query engine. This is how my package ultimate looks like (attachemen #1). The
sever_lambda.js
contains all the typescript code. I use type-grapql and the type-graphql-prisma plugin. I package this with esbuild by requiring all the generated prisma files in the entrypoint. Then I have this
deploy.sh
script:
Copy code
#!/usr/bin/env bash
rm -rf build
ts-node build.ts
mkdirp -p ./build/node_modules/
cp -r ./node_modules/.prisma ./build/node_modules/
rm ./build/node_modules/.prisma/client/libquery_engine-darwin.dylib.node
cd aws && AWS_PROFILE=profile npx cdk deploy
In my case, I use the PlanetScale database, so I have no pooling logic in the database connections, too.
The
build.ts
file:
Copy code
import { build } from 'esbuild'
import { esbuildDecorators } from '@anatine/esbuild-decorators'

async function myBuilder(
  tsconfig?: string,
  entryPoints?: string[],
  outfile?: string,
  cwd: string = process.cwd()
) {
  const buildResult = await build({
    platform: 'node',
    target: 'node14',
    bundle: true,
    plugins: [
      esbuildDecorators({
        tsconfig,
        cwd,
      }),
    ],
    tsconfig,
    entryPoints: ['server_lambda.ts'],
    outfile: './build/server_lambda.js',
    external: [
      // This is likely to be your friend...
    ],
  })
  console.log(buildResult)
}

myBuilder().then(() => {
  console.log('done')
})
The
server_lambda.ts
file is just a
apollo-server-lambda
compatible entrypoint that also inits the prisma-client and imports all the resolvers and other dependencies so that esbuild can package it cleanly.
For the CDK stack, it looks like:
Copy code
import * as cdk from '@aws-cdk/core'
import * as path from 'path'
import * as lambda from '@aws-cdk/aws-lambda'
import * as apiGateway from '@aws-cdk/aws-apigatewayv2'
import { LambdaProxyIntegration } from '@aws-cdk/aws-apigatewayv2-integrations'

export class HttpApiStack extends cdk.Stack {
  constructor(scope: <http://cdk.App|cdk.App>, id: string, props?: cdk.StackProps) {
    super(scope, id, props)


    const handler = new lambda.Function(this, 'api', {
      runtime: lambda.Runtime.NODEJS_14_X,
      code: lambda.Code.fromAsset(path.join(__dirname, '../../build')),
      handler: 'server_lambda.graphqlHandler',
      timeout: cdk.Duration.seconds(10),
      memorySize: 512,
      environment: {
        DATABASE_URL: 'connection string for prisma here',
      },
    })

    const apiIntegration = new LambdaProxyIntegration({
      handler
    })
    const httpApi = new apiGateway.HttpApi(this, 'apigateway')
    httpApi.addRoutes({
      path: '/{proxy+}',
      integration: apiIntegration,
    })

  }
}
this results in about a 53mb large lambda, way below the 250mb limit. With the caveat that the migration engine is not included in this setup!
You may want to include things from the @prisma package instead of from the .prisma like I do if you intend to do migrations in lambda(but I wouldn’t recommend that!)
Oh and in
prisma.schema
you need to add this:
Copy code
binaryTargets   = ["native", "rhel-openssl-1.0.x"]
under your
generator
config
If you use planetscale, you have afully serverless code and db with a single source of truth(prisma.schema) and you can further use https://www.graphql-code-generator.com/ for frontend apps and cli’s(and more) to leverage the prisma shemas outputs. It’s really magical and ridiculously productive 🙂
✅ 1
c
The easiest way, by far, to get that backend into production on AWS is to use Heroku.