Build on the supported package contract
Use @absolutejs/errors-postgres through its supported public entry points.
@absolutejs/errors-postgresv0.1.3betaObservabilityPostgres-backed, Effect-native IssueStore for @absolutejs/errors with first-class Drizzle and tagged-template adapters.
bun add @absolutejs/errors-postgresPostgres-backed, Effect-native IssueStore for @absolutejs/errors — the durable "Issues" surface (Sentry's product core), self-hosted on your own Postgres.
Durable grouped issues + an append-only event timeline, with new vs. regression detection resolved in a single atomic CTE upsert — one round-trip, no transaction, so it works over Neon's HTTP driver too.
Drizzle
Re-export the package tables from your application schema and manage them with your normal migration workflow:
The Drizzle store uses transactions for atomic event/group updates, portable native JSONB for tags and extra context, row locking for regression detection, and the same Effect error channel as the tagged-template adapter. JSONB values are passed to Drizzle drivers as native objects (rather than pre-serialized strings), preventing Bun SQL from storing them as JSON strings.
Tagged-template compatibility
Works identically with @neondatabase/serverless:
Every method returns an Effect with a typed IssueStoreError channel (IssueStoreSchemaError / IssueStoreQueryError / IssueStoreSerializationError) — failures are values, not throws.
Method — Effect
record(event) — atomic upsert (one event) → { issue, isNew, isRegression }
recordCoalesced(group) — count-aware upsert + bulk unnest insert — one round-trip per herd
listIssues(filter?) — dashboard list (project / environment / state / ILIKE title), newest-first
getIssue(project, fingerprint) — Option<IssueRecord>
setState(project, fingerprint, state) — resolve / ignore / unresolve
assign(project, fingerprint, who \ — null) — triage
listEvents(project, fingerprint, limit?) — occurrence timeline, newest-first
Grouping semantics (mirrors createMemoryIssueStore exactly)
new vs. regression — detected in one statement: xmax = 0 ⇒ the row
was inserted (new); a CTE captures the pre-update state, so a resolved issue seen again is a regression and flips back to unresolved. ignored issues stay muted.
severity escalates, never de-escalates — fatal > error > warning > info.
Created on first use (set ensureSchema: false to manage it via migrations). tablePrefix defaults to error → error_issues + error_events.
Indexes: (project, last_seen DESC) and (project, state) on issues; (project, fingerprint, at DESC) on events.
trace_id / span_id (→ @absolutejs/telemetry) and replay_id (→ @absolutejs/replay) are stored per event so a dashboard can cross-link an issue to its exact trace and DOM replay.
Choose the schema-derived Drizzle store for application-managed databases or the raw tagged-template compatibility store for lightweight and Neon HTTP integrations.
Outcomes
Use @absolutejs/errors-postgres through its supported public entry points.
Hardening checklist
Follow in order
Re-export the package tables from your application schema and manage them with your normal migration workflow:
export { errorEvents, errorIssues } from "@absolutejs/errors-postgres";Re-export the package tables from your application schema and manage them with your normal migration workflow:
import { createDrizzleIssueStore } from "@absolutejs/errors-postgres";
const store = createDrizzleIssueStore({ db });Supported entry points declared by this package manifest.
Package entry point declared in package.json.
Scripts declared by this package manifest.
Search the declarations exported by the current package type files. Expand a symbol to inspect its source-backed signature.