---
title: "@playstack/events-prisma"
description: "Transactional Postgres outbox storage for Playstack events using a structural Prisma boundary."
tags: ["package","events","prisma","outbox","free"]
---

{/* package-access:start */}

> **Free.** MIT licensed. Check preview availability before installing. See [package access](/docs/packages#access-policy).

{/* package-access:end */}

`@playstack/events-prisma` persists observational envelopes in the same Postgres transaction as application state, then drains them through an application-owned publisher.

{/* package-install:start */}

## Install

After confirming [preview access](/docs/packages#access-policy), install the package at your application's shared Playstack version:

```sh
npm install --save-exact @playstack/events-prisma@0.1.0-beta.1
```

Check the peer requirements below before choosing a runtime or provider.

{/* package-install:end */}

## Install and compose

```ts
import { createEventBridge } from '@playstack/events'
import {
  PrismaEventOutboxWriter,
  PrismaOutboxPump,
} from '@playstack/events-prisma'

const outbox = new PrismaEventOutboxWriter()
const bridge = createEventBridge({ registries, clock, ids, outbox, routes })

const pump = new PrismaOutboxPump({
  client: prisma,
  publisher: queuePublisher,
  clock,
})

await pump.runOnce()
```

The writer’s transaction kind is `prisma`; package persistence must pass the same transaction handle to `events.emit`.

## Pump configuration

| `PrismaOutboxPumpOptions` property | Required | Purpose |
| --- | --- | --- |
| `client` | Yes | Structural root Prisma client; exposed as `pump.client`. |
| `publisher` | Yes | Publishes an envelope with a stable `jobId`. |
| `clock` | Yes | Claim, lease, retry, delivery, and cleanup time. |
| `batchSize` | No | Maximum rows per run; defaults to 100. |
| `leaseMs` | No | Renewable claim lease; defaults to 60 seconds. |
| `retryDelayMs` | No | Positive delay function by attempt; defaults to bounded exponential backoff. |

`runOnce()` returns claimed, delivered, and failed counts. `cleanup(retentionMs?)` removes delivered transport rows after 24 hours by default.

## Publisher bridge

```ts
interface OutboxPublisher {
  publish(event: EventEnvelope, options: { jobId: string }): Promise<void>
}
```

The publisher must use the outbox ID as the transport idempotency key. A process crash after publish but before `deliveredAt` can republish the same row; stable job identity makes the handoff safely at-least-once.

Claims use one parameterized `UPDATE … FOR UPDATE SKIP LOCKED … RETURNING` query, allowing concurrent pumps. Failed rows release their lease and receive bounded backoff. UTC normalization makes claim and recovery independent of database session timezone.

## Boundary

The adapter owns outbox persistence, claims, leases, and transport-row cleanup. It does not select a broker, start a poller, create or disconnect Prisma, define consumer policy, or provide a replayable domain log. The application owns migrations and pump lifecycle.

{/* package-reference:start */}

## API entry points and requirements

Reference snapshot: `@playstack/events-prisma@0.1.0-beta.1`. Import only the entry point your runtime needs. Paths below are relative to the installed package; use **Go to Definition** in your editor to inspect exact parameters, return types and overloads. Do not import the declaration-file paths directly.

| Public entry point | Declaration file |
| --- | --- |
| `@playstack/events-prisma` | `./dist/index.d.ts` |
| `@playstack/events-prisma/testing` | `./dist/testing.d.ts` |
| `@playstack/events-prisma/playstack.artifacts.json` | No TypeScript declaration (asset or metadata export). |
| `@playstack/events-prisma/package.json` | No TypeScript declaration (asset or metadata export). |

Node.js engine requirement: `>=20`. This is not a claim that every entry point works in browsers or Workers.

### Peer dependencies

This package declares no peer dependencies. Its ordinary dependencies are resolved by the package manager.

For a complete first program, start with [Getting started](/docs/getting-started). For API lookup and partial-example conventions, see [Reading the reference](/docs/packages#reading-the-reference). Provider failures, lifecycle requirements and application responsibilities remain described in the guide above; types alone do not establish production safety.

{/* package-reference:end */}
