Skip to main content
The ClickHouse connector inserts Novu webhook events into a ClickHouse table over the ClickHouse HTTP interface. Use it when you want notification events in ClickHouse for analytics without running your own ingestion service. Novu webhook delivery is powered by Svix. This connector maps to the Svix ClickHouse advanced endpoint.
Outbound webhooks are available on Team and Enterprise plans.

Prerequisites

  • A ClickHouse server reachable over its HTTP or HTTPS interface, for example port 8443 for HTTPS or 8123 for HTTP. The native protocol port (9000) is not used.
  • A ClickHouse user with a password and INSERT permission on the destination table.
  • The destination table created before you enable the endpoint. The connector does not create or alter tables.

Configuration

Grant insert permission

Give the connector user insert access on the destination table only. ClickHouse GRANT syntax:

Default destination behavior

Without a transformation, Svix inserts each webhook payload directly using the ClickHouse JSONEachRow format. Top-level payload fields are matched to columns by name. ClickHouse is different from the other warehouse connectors in one important way: it does not add any columns of its own. There is no generated id column and no payload column unless you define them. You own the full schema. Novu webhook bodies are nested, and message fields such as subscriberId and channel sit under data.object rather than at the top level. Because of that, plan on writing a transformation for this connector unless your table columns exactly match the top-level keys of the webhook body.

Create the destination table

This table stores a few flattened fields plus the full webhook body:
received_at is not returned by the transformation below. Columns omitted from a JSONEachRow row take their declared default, so ClickHouse fills the insert time.

Transformation contract

The transformation receives one batch and returns the rows to insert: The handler receives one delivery batch:
  • input.events, an array whose length is capped by the endpoint batch size
  • input.events[].eventType, the Novu event type, for example message.sent
  • input.events[].payload, the webhook body
The webhook body wraps the resource in an envelope. payload.object is the resource type as a string, such as "message", and the resource itself is under payload.data.object. For message events, fields such as subscriberId and channel are therefore at event.payload.data.object. Other event families use different resource shapes, so guard extracted fields with defaults.
  • Output: an object with a rows array. Each row is an object whose keys match your ClickHouse column names. Each row is inserted separately using JSONEachRow.
Novu-oriented example that reads message fields from event.payload.data.object:
Stringify nested values. A row value that is itself an object or array will not insert into a String column.

Configure in the Dashboard

1

Add the endpoint

Open Webhooks in the Novu Dashboard, select Endpoints, click Add Endpoint, and choose .
2

Enter connection details

Enter the URL, username, password, table name, and database.
3

Configure the transformation

Paste the transformation above and adjust the keys so they match your column names exactly.
4

Select event types

Subscribe to the event types you want to store. If you subscribe to more than one, confirm the transformation produces valid rows for every one of them, since a single table receives all of them.
5

Test the endpoint

Click Create, open the endpoint, go to the Testing tab, and use Send Example for each subscribed event type. Confirm success in the Logs tab.

Verify delivery

Query the table with clickhouse-client:
Or over the same HTTP interface the connector uses:

Troubleshooting

Official references