This project shows an example of how you might use PostGraphile on Lambda. It has the following aims:
- Startup without needing to introspect database
- Fast startup
- Small bundle size
- JWT auth supported OOTB
- Graphile-build schema plugin support
- Support for middlewares
- No requirement for Node.js
http
-based libraries (such as Connect, Express, Koa)
Postgraphile-lambda-example does NOT intend to watch the schema for changes; this means that you must build and release a new version every time you change your database. (You only need to update the cache file though.)
Postgraphile-lambda-example does NOT intend to make this fully compatible with
the postgraphile
CLI - this will be a subset best suited to Lambda usage.
Postgraphile-lambda-example does NOT intend to support subscriptions.
We use the following tools:
- webpack - to bundle up the required code into as small a file as possible
(no need for
node_modules
any more!) - PostGraphile
writeCache
/readCache
- we'll introspect the database during the build and write the results to a cache file to be included in the bundle; then when the Lambda service starts up it can read from the cache rather than introspecting the database again.
First clone this repository locally, and install dependencies:
yarn
Next, set up a .env
file matching your environment:
cp .env.template .env
And modify the src/postgraphileOptions.js
file to your taste.
Finally run:
yarn build
This will result in a lambda.zip
file that you can upload to Amazon Lambda.
- Visit https://console.aws.amazon.com/lambda/home and click 'Create function'
- Select "Author from scratch" and give your function a name, select the most recent Node.js release (at least 8.10+), create (or select) a role (I granted "Simple microservice permissions")
- Click "Create function" and wait about 15 seconds; you should be greeted with a "Congratulations" message.
- Scroll to "Function code", select "Upload a .zip file" from "Code entry type", press the "Upload" button and select the
lambda.zip
file you generated above; then click "Save" - Scroll to "Environment variables" and enter your
DATABASE_SCHEMAS
andDATABASE_URL
settings; then click "Save" - Scroll to the top and select "API Gateway" under "Add triggers" in the "Designer", then scroll to "Configure triggers"
- Create a new API; if you like add 'image/gif', 'image/png', 'image/icon' and 'image/x-icon' to the list of binary media types; then press "Add" followed by "Save"
- Click the name of the API gateway to go to the API gateway config
- Select the
/
route underResources
and from the "Actions" dropdown, select "Create method" add create anANY
method - Turn on "Lambda Proxy Integration" and enter your lambda function name in the relevant box, then press "Save"
- Finally, go to "Actions" again and "Deploy API"
- Copy the "Invoke URL" and paste it into your GraphQL client of choice - you can now talk to your Lambda PostGraphile API 😅
If you want GraphiQL support (STRONGLY DISCOURAGED! Use an external GraphQL
client such as GraphiQL.app, Altair or GraphQL Playground instead!), then you
need to go back to stage 9, and choose 'Create Resource', tick "Configure as a
proxy resource", press "Create Resource" and then configure it with the name of
your lambda function, you should also change the settings in
src/postgraphileOptions.js
(see comment in that file).
The system operates based on a number of phases. Each phase depends on the previous non-optional phase; so if an earlier phase rebuilds then all later phases must also rebuild.
Uses webpack to produce a single JS file containing all that is necessary,
using src/index.js
as the entry point.
Compiles src/**
to dist/
Start here when: you change your code, add/remove plugins, or upgrade dependencies.
Uses a similar approach to postgraphile --write-cache
to write a cache file
containing introspection details of your database.
Generates dist/postgraphile.cache
Start here when: database schema changes.
Produce a zip file combining the two artifacts above - dist/index.js
and dist/postgraphile.cache
.
Generates lambda.zip
from dist/
folder
Launch the bundle in the sam local
test environment, and run a series of requests.
Manual checking of the results is required.
Left as an exercise to the reader.
- docker
- aws sam cli -
pip install aws-sam-cli
Install dependencies
yarn
Copy .env.template to .env and customize as you like:
cp .env.template .env
If you're using the default .env.template
file then you'll need to populate the
postgraphile_forum_example
database:
./scripts/import-example-database
Make sure that the query in test/query.graphql
and the options in src/postgraphileOptions.js
are both valid for your database. If you're using a remote PostgreSQL server (or one within a docker instance), you may need to update the host.docker.internal
reference in test/make-template-yml.sh
(line 15).
Run the tests:
yarn test
Note the first run might take a while whilst the system installs the relevant docker images.
In the test output you should see a number of 0 error(s)
statements, and some successful GraphQL HTTP request payloads
Do the same as for the test, but instead of running yarn test
at the end, instead run:
yarn sam
This will set up a local GraphQL endpoint at http://127.0.0.1:3000/
You can then use a GraphQL client such as Altair or GraphQL Playground to issue requests.
If you're using the sample database then you can generate a JWT via:
mutation {
authenticate(input: { email: "[email protected]", password: "iFbWWlc" }) {
jwtToken
}
}
Then set the JWT header:
{
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9ydW1fZXhhbXBsZV9wZXJzb24iLCJwZXJzb25faWQiOjEsImlhdCI6MTUzODEyOTEyMSwiZXhwIjoxNTM4MjE1NTIxLCJhdWQiOiJwb3N0Z3JhcGhpbGUiLCJpc3MiOiJwb3N0Z3JhcGhpbGUifQ.NFZ10gvIB29VL1p3Wh-Cc74JSigOOhgtqaMCP9ZA2W0"
}
Then you can issue an authenticated query:
{
currentPerson {
nodeId
id
fullName
}
}
Note that SAM unpacks the zip and reboots node for every single request, so you're going to suffer some startup latency with this.
Improvements to PostGraphile's support for Lambda were sponsored by Connecting Good