Prisma Pulse: Trigger Functions from database changes

Prisma Pulse integrates with Inngest, transforming database changes into Inngest Events.

Connecting Prisma Pulse to your database will trigger a new row in the users table, creating a db/user.created event that can trigger Inngest Functions (for example, a user onboarding email sequence).

Prisma Pulse watches your database for changes and streams them to your Inngest Pulse Router. The Inngest Pulse Router translates the Prisma Pulse stream events into Inngest Events that later trigger Inngest Functions.

Setup Prisma Pulse

Using Prisma Pulse requires some configuration changes on both your Prisma Data Platform account and database.

Please refer to the Prisma Pulse documentation to enable it.

Setup and deploying the Inngest Pulse Router

Once Prisma Pulse enabled on your account, you'll have to deploy a Inngest Pulse Router, responsible for translating Prisma Pulse events into Inngest events.

The following command will generate for you the Inngest Pulse Router in your application:

npx try-prisma -t pulse/inngest-router

Configuring the watched tables

The list of watched tables should be configured in the src/index.ts file by updating the following list:

src/index.ts

// Here configure each prisma model to stream changes from
const PRISMA_MODELS = ['notification', 'user'];

Deploying the Inngest Pulse Router

The Inngest Pulse Router is a Node.js program opening a websocket connection with the Prisma Pulse API. The following environment variables are required:

Due to its long-lived nature, the Inngest Pulse Router needs to be deployed on a Cloud Provider such as Railway.

You will find instructions to deploy your router on Railway on this GitHub README.

Using Prisma Pulse with Serverless

The Inngest Pulse Router can also be deployed on Serverless by leveraging the Delivery Guarantees of Pulse events.

By passing a name to your prisma.model.stream({ name: "inngest-router" }), Prisma Pulse will keep track of received events and only send the new ones (since the last connection).

We can leverage this mechanism by creating a Inngest Functions trigger by a CRON schedule and running on a Serverless Function. The Inngest Function will run every 15min and collect the first 100 updates before finishing.

Trigger a Function from a database event

Once your Inngest Pulse Router deployed, Inngest events matching your database changes will be triggered.

All events follow the following format: "db/<table>.<action>" with <action> part of:

  • create
  • update
  • delete

The events sent by the Inngest Pulse Router contains the changed data, as described in this API Reference.

Here is an example of a onboarding workflow followed upon each new account creation:

app/inngest/functions.ts

import { inngest } from "./client";
import { sendEmail } from "@/lib/email"

export const handleNewUser = inngest.createFunction(
  { id: "handle-new-user" },
  { event: "db/user.create" },
  async ({ event, step }) => {
    // This object includes the entire record that changed
    const pulseEvent = event.data;

    await step.run("send-welcome-email", async () => {
  		// Send welcome email
      await sendEmail({
        template: "welcome",
        to: pulseEvent.created.email,
      });
    });

    await step.sleep("wait-before-tips", "3d");

    await step.run("send-new-user-tips-email", async () => {
      // Follow up with some helpful tips
      await sendEmail({
        template: "new-user-tips",
        to: pulseEvent.created.email,
      });
    });
  },
);

Best practice

A Function run performing a database change might trigger a Prisma Pulse event that will run the Function again.

We recommend using "db/*" events in combination with a if: filter to avoid any infinite loop of Function runs triggered.

See an example in this blog post.