Skip to content

Commit 0bef4ee

Browse files
nicktrnericallam
authored andcommitted
feat(webapp): add EVENTS_READER_CLICKHOUSE_URL for events read replica
The events client both inserts events and reads traces/spans/logs through one instance. Give it a dedicated reader URL so reads can move to a replica while inserts stay on EVENTS_CLICKHOUSE_URL. Unlike the read-only clients, it does not fall back to CLICKHOUSE_READER_URL: a write-capable client only moves reads on an explicit opt-in.
1 parent e4e24ea commit 0bef4ee

3 files changed

Lines changed: 11 additions & 4 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: improvement
4+
---
5+
6+
Add `EVENTS_READER_CLICKHOUSE_URL` to send trace/span/log reads to a read replica while event inserts stay on `EVENTS_CLICKHOUSE_URL`. Optional; unset keeps reads and writes on the same instance.

apps/webapp/app/env.server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,6 +1816,8 @@ const EnvironmentSchema = z
18161816
.string()
18171817
.optional()
18181818
.transform((v) => v ?? process.env.CLICKHOUSE_URL),
1819+
// Events read replica (traces/spans/logs). No CLICKHOUSE_READER_URL fallback by design: this write-capable client opts in explicitly.
1820+
EVENTS_READER_CLICKHOUSE_URL: z.string().optional(),
18191821
EVENTS_CLICKHOUSE_KEEP_ALIVE_ENABLED: z.string().default("1"),
18201822
EVENTS_CLICKHOUSE_KEEP_ALIVE_IDLE_SOCKET_TTL_MS: z.coerce.number().int().optional(),
18211823
EVENTS_CLICKHOUSE_MAX_OPEN_CONNECTIONS: z.coerce.number().int().default(10),

apps/webapp/app/services/clickhouse/clickhouseFactory.server.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,9 @@ function initializeEventsClickhouseClient(): ClickHouse {
307307
maxOpenConnections: env.EVENTS_CLICKHOUSE_MAX_OPEN_CONNECTIONS,
308308
};
309309

310-
// This client both inserts events and reads traces/spans/logs. When a reader replica
311-
// is configured, split it so queries hit the replica while inserts stay on the writer.
312-
if (env.CLICKHOUSE_READER_URL) {
313-
const readerUrl = new URL(env.CLICKHOUSE_READER_URL);
310+
// Mixed read+write client: split reads to its own EVENTS_READER_CLICKHOUSE_URL (not the global reader) so inserts can never hit the replica.
311+
if (env.EVENTS_READER_CLICKHOUSE_URL) {
312+
const readerUrl = new URL(env.EVENTS_READER_CLICKHOUSE_URL);
314313
readerUrl.searchParams.delete("secure");
315314

316315
if (readerUrl.toString() !== writerUrl.toString()) {

0 commit comments

Comments
 (0)