feat(webapp): add option to disable PostgreSQL task-event writes (#4242)

## Summary

Adds `EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED` (default off), which
makes the task-event store skip all PostgreSQL `TaskEvent` writes. It's
for deployments that store task events in ClickHouse
(`EVENT_REPOSITORY_DEFAULT_STORE=clickhouse_v2`) and no longer want the
PostgreSQL copy.

## How it works

The guard sits at the single postgres write boundary,
`TaskEventStore.create` / `createMany`, so it covers every write path
(OTLP ingestion and run-lifecycle events) with one check. Reads are
untouched (`findMany` / trace queries / streaming), so existing
PostgreSQL events remain readable.

Leave it off unless the default store is `clickhouse_v2`, otherwise task
events for any run still routed to PostgreSQL would be dropped.
This commit is contained in:
Eric Allam
2026-07-13 17:17:02 +01:00
committed by GitHub
parent 6e943f2421
commit 29598a77b8
4 changed files with 19 additions and 2 deletions
@@ -0,0 +1,6 @@
---
area: webapp
type: feature
---
Added `EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED` to skip all PostgreSQL task-event writes for deployments that store task events in ClickHouse. Leave it off unless `EVENT_REPOSITORY_DEFAULT_STORE` is `clickhouse_v2`, otherwise task events are lost.
+1
View File
@@ -1860,6 +1860,7 @@ const EnvironmentSchema = z
.enum(["postgres", "clickhouse", "clickhouse_v2"])
.default("postgres"),
EVENT_REPOSITORY_DEBUG_LOGS_DISABLED: BoolEnv.default(false),
EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED: BoolEnv.default(false),
EVENTS_CLICKHOUSE_MAX_TRACE_SUMMARY_VIEW_COUNT: z.coerce.number().int().default(25_000),
EVENTS_CLICKHOUSE_MAX_TRACE_DETAILED_SUMMARY_VIEW_COUNT: z.coerce.number().int().default(5_000),
EVENTS_CLICKHOUSE_MAX_LIVE_RELOADING_SETTING: z.coerce.number().int().default(2000),
@@ -157,14 +157,23 @@ export class EventRepository implements IEventRepository {
}
private async insertImmediate(event: CreateEventInput) {
if (env.EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED) {
return;
}
await this.#flushBatch(nanoid(), [this.#createableEventToPrismaEvent(event)]);
}
insertMany(events: CreateEventInput[]) {
if (env.EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED) {
return;
}
this._flushScheduler.addToBatch(events.map(this.#createableEventToPrismaEvent));
}
async insertManyImmediate(events: CreateEventInput[]) {
if (env.EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED) {
return;
}
await this.#flushBatchWithReturn(nanoid(), events.map(this.#createableEventToPrismaEvent));
}
@@ -1018,7 +1027,7 @@ export class EventRepository implements IEventRepository {
if (options.immediate) {
await this.insertImmediate(event);
} else {
this._flushScheduler.addToBatch([this.#createableEventToPrismaEvent(event)]);
this.insertMany([event]);
}
}
@@ -1152,7 +1161,7 @@ export class EventRepository implements IEventRepository {
if (options.immediate) {
await this.insertImmediate(event);
} else {
this._flushScheduler.addToBatch([this.#createableEventToPrismaEvent(event)]);
this.insertMany([event]);
}
return result;
+1
View File
@@ -135,6 +135,7 @@ mode: "wide"
| `SERVER_OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` | No | 8192 | OTel span attribute value length limit. |
| **Task events** | | | |
| `EVENT_REPOSITORY_DEFAULT_STORE` | No | postgres | Where to store task events. Set to `clickhouse_v2` to store in ClickHouse (recommended for production). |
| `EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED` | No | 0 | Skip all PostgreSQL task-event writes (set to `1`). Only enable when `EVENT_REPOSITORY_DEFAULT_STORE` is `clickhouse_v2`, otherwise task events are lost. |
| **Realtime** | | | |
| `REALTIME_STREAM_VERSION` | No | v1 | Stream version exposed to tasks via the `TRIGGER_REALTIME_STREAM_VERSION` variable. Distinct from `REALTIME_STREAMS_DEFAULT_VERSION`. One of `v1`, `v2`. |
| `REALTIME_STREAM_MAX_LENGTH` | No | 1000 | Realtime stream max length. |