Trigger AWS Lambda functions from PostgreSQL (RDS/Aurora) using Serverless Framework events. This plugin creates a Postgres trigger that sends row-change payloads to your Lambda via the aws_lambda extension.
- Events:
INSERT,UPDATE,DELETE - Scope: Only
AFTER ROWtriggers (with optionalWHENpredicate) - Lifecycle: Triggers are created after deploy and dropped before remove
- Payload: Sends
type,schema,table,record, andold_recordas JSON
- Serverless Framework v3
- PostgreSQL with extensions:
pgcrypto,aws_commons,aws_lambda - Your DB instance/cluster must be allowed to invoke Lambda (via an IAM role with
lambda:InvokeFunction). See AWS docs: Integrating Amazon Aurora PostgreSQL with AWS Lambda - The database user in your
connectionStringmust be able to:CREATE EXTENSION(or the extensions must already exist)CREATE SCHEMAandCREATE FUNCTIONGRANTexecute/usage on theaws_lambdaandaws_commonsschemas
pnpm add -D serverless-postgres-event
# or
npm i -D serverless-postgres-event- If the repo commits
dist/, install directly:
pnpm add -D your-org/serverless-postgres-event#v0.1.0
# or
npm i -D your-org/serverless-postgres-event#main- If the repo does NOT commit
dist/, it should include a"prepare": "tsc"script so install from Git can build TypeScript on install. Make sure lifecycle scripts are allowed in your environment.
# serverless.yml
plugins:
- serverless-postgres-event# serverless.yml
custom:
postgres:
# Either set the connection string here...
# connectionString: postgres://user:pass@host:5432/dbname
# ...or via environment variable:
# PG_CONNECTION_STRING=postgres://user:pass@host:5432/dbname
# Optional overrides:
# namespace: sls_${self:service}_${sls:stage} # default: slugified "sls_<service>_<stage>"
# postgresRoleName: ${self:custom.postgres.namespace}_lambda_invoker # Postgres role owning SQL invoker
# lambdaInvokerFunctionName: lambda_invoker # SQL function that invokes AWS Lambda
# Deprecated (still supported for backward-compatibility):
# roleName: ${self:custom.postgres.namespace}_lambda_invoker
# functionName: lambda_invoker- At initialization, the plugin asserts a connection string exists (either
custom.postgres.connectionStringorPG_CONNECTION_STRINGenv var). - The plugin will:
- Ensure
pgcrypto,aws_commons,aws_lambdaextensions exist - Create schema
${namespace}if not present - Create a SQL function
${namespace}.${lambdaInvokerFunctionName}()(owned by${postgresRoleName}) - Grant required usage/execute permissions to
${postgresRoleName}
- Ensure
functions:
onEventChange:
handler: src/handler.main
events:
- postgres:
table: public.events
operations: [INSERT, UPDATE, DELETE] # at least one required
order: AFTER # only AFTER supported
level: ROW # only ROW supported
when: "NEW.status = 'PUBLISHED'" # optional SQL predicate- Only one
postgresevent is supported per function. - Triggers are created:
- After full deploy:
after:deploy:deploy - After single function deploy:
after:deploy:function:deploy
- After full deploy:
- Triggers are dropped:
- Before remove:
before:remove:remove
- Before remove:
The plugin invokes your Lambda with a JSON payload like:
{
"type": "INSERT",
"schema": "public",
"table": "events",
"record": { "...": "new row (for INSERT/UPDATE)" },
"old_record": { "...": "old row (for UPDATE/DELETE)" }
}Example handler (TypeScript):
export const main = async (event: {
type: 'INSERT' | 'UPDATE' | 'DELETE';
schema: string;
table: string;
record: Record<string, unknown> | null;
old_record: Record<string, unknown> | null;
}) => {
// Your logic here
console.log(event);
};- The plugin scans functions for
postgresevents and computes each function’s ARN from the current AWS account/region. - It creates a Postgres trigger per event that calls
${namespace}.${lambdaInvokerFunctionName}('<lambda-arn>'). - The SQL function calls
aws_lambda.invoke(...)with the JSON payload (event type + row data).
- Only
AFTER ROWtriggers are supported. - One
postgresevent per function. - The DB instance/cluster must be permitted to call your Lambda (IAM role + policy).
- Multi-region or cross-account requires the ARN to be resolvable in the target account/region used by Serverless.
- Build:
pnpm build(runstsc, outputs todist/) - Optional type declarations: enable
declarationintsconfigand add"types": "dist/index.d.ts"topackage.json. - For GitHub installs without published npm package, add:
{
"scripts": { "prepare": "tsc" }
}ISC