Sinks
Infrastructure

Sinks

Route notification events to external systems

A sink is a destination for structured send events. withEventLogger calls sink.write(event) once per send — the sink decides where the event goes.

When to use a sink

Use a sink when you need a durable, structured record of every send — not just logs. Sinks are the right tool when:

  • Audit trails — you need to prove a notification was sent (or failed) for compliance, billing, or support investigations.
  • Analytics — you want to track delivery rates, latency distributions, or error patterns over time in a data warehouse or dashboard.
  • Alerting — you want to page on-call when a route starts failing, without coupling alert logic to the send pipeline.
  • Event streaming — you want to feed notification events into a Kafka topic, S3 bucket, or webhook for downstream systems to consume.

If you only need console output for debugging, the logger is simpler. If you need per-request spans with parent-child relationships, use a tracer instead. Sinks sit between the two — more structured than logs, less granular than traces.

The EventSink interface

Prop

Type

The SendEvent shape

Every event carries the same base fields:

Prop

Type

Built-in sinks

consoleEventSink

Logs events to the console. Use during local development.

import { consoleEventSink } from '@betternotify/core/sinks';

withEventLogger({ sink: consoleEventSink() });

inMemoryEventSink

Collects events in an array. Use in tests to assert on what was sent.

import { inMemoryEventSink } from '@betternotify/core/sinks';

const sink = inMemoryEventSink();
// after sending:
console.log(sink.events.length);
console.log(sink.events[0].status);

Custom sinks

Use createEventSink to build a sink from a write function. It wraps your function with failure isolation (a sink crash never breaks the send pipeline) and optional event filtering:

import { createEventSink } from '@betternotify/core/sinks';

const datadogSink = createEventSink({
  write: async (event) => {
    await fetch('https://api.datadoghq.com/api/v2/logs', {
      method: 'POST',
      headers: { 'DD-API-KEY': process.env.DD_API_KEY! },
      body: JSON.stringify(event),
    });
  },
});

Prop

Type

Filtering events

Ship only errors to a paging pipeline, or only successes to an analytics sink:

const errorOnlySink = createEventSink({
  write: async (event) => { await alertService.send(event); },
  filter: (event) => event.status === 'error',
});

On this page