See every error before it sees you.
CodeRadar is the portfolio's error tracker, distributed tracer, and alerting plane. One ingest pipeline, every product, every environment. Search and filter the whole stack in real time.
Sentry tells you what broke. Datadog charges per host to do the same. CodeRadar is built for the inside of one venture studio: every product becomes a project under one Goodventures org, errors flow from each app's SDK into a unified backend, and the dashboard lets you scrub through traces and triage incidents across the entire fleet without a billing meter running in the background.
Error tracking, distributed tracing, and alerting — built for the whole portfolio at once.
One ingest, one query backend, one dashboard. Every product is a project, every project shares the same infrastructure, every error and trace is searchable across the fleet in real time. Built on the open CodeWatch core, repackaged as the portfolio's Sentry-equivalent.
Twelve features that ship in the box.
CodeRadar absorbs the day-one Sentry workflow — capture, search, triage, alert — and adds the operating model the Goodventures portfolio actually needs: one org, every product as a project, sampling and quotas under your control, source-map auto-resolution from your release pipeline.
Ingest pipeline
Hono + TypeScript OTLP-native edge service. Accepts batched events from every SDK, fingerprints in ClickHouse, broadcasts via Redis pub/sub. Backpressure-aware with per-project quotas.
Query backend
PostgreSQL for metadata (projects, users, releases, alert rules). ClickHouse for the high-volume event log. The split keeps the metadata store fast and the event store cheap to scale.
Real-time dashboard
Next.js 15 dashboard streams over Server-Sent Events. New errors appear in the feed within a second of being captured. Pin a query, watch it update live.
Search and filter
Query language: project:truecom level:error in:5m user.id:u_*. Filter on level, environment, release, runtime, browser, OS, tags, fingerprint, user, country.
Smart alerting
Threshold rules (rate, count, percent change) and pattern rules (new fingerprint, regression). Channels: Slack, email, generic webhook. PagerDuty integration on the roadmap.
Source-map auto-resolution
Upload source maps on every release via the SDK release hook, or have CodeRadar fetch them from a release URL. Browser stack traces resolve to original source by default.
Breadcrumbs
Each captured error carries the last 100 client-side breadcrumbs: console messages, fetch calls, navigation events, custom tags. Configurable buffer per SDK.
Distributed traces
W3C tracecontext on every outbound request from the SDK. Cross-service traces through OTLP. View span tree, timing waterfall, service map for a single trace.
Session replay roadmap
Lightweight DOM snapshot + diff stream attached to errors so you can replay the user's last 30 seconds before the crash. Behind a feature flag in early-access. Off by default.
Quotas + sampling
Per-project event allowance. Per-environment sample rate. Adaptive sampling that holds error events at 100% and traces at the configured rate. Burn-rate alarms when a project nears its quota.
Multi-tenant routing
One Goodventures org, every product is a project. Project DSN routes events into the right tenant. Row-level isolation in Postgres + ClickHouse keyed on project_id.
Auth + access
Clerk-backed sign-in at app.coderadar.app. [email protected] is org admin. Per-project member assignment via the org settings.
Search across every project. Filter to one. Pin it. Live-update it.
Fourteen products, one query box. Filter by project, level, environment, release, fingerprint, user, runtime, browser, country, tag, or any custom attribute the SDK shipped. Saved queries appear in the dashboard side panel; pinned queries stream new matches over SSE.
One org. Every product is a project. [email protected] is admin.
CodeRadar is portfolio-native. There isn't a separate Sentry account per product, no per-project billing meter, no SSO sprawl. Sign in with the Goodventures Clerk session, see every project, switch between them with a project picker. Members are added to projects, not to orgs — there is only ever one org.
Five lines of code. Every error, every trace.
Install the SDK, set the DSN, instrument runs automatically. Express, Next.js, Hono, FastAPI, and net/http frameworks are auto-instrumented. Browser SDK is a single script tag. Detailed setup guides at /docs/sdks/.
// 1. install // $ pnpm add @coderadar/sdk // 2. init at process boot import { init } from "@coderadar/sdk"; init({ dsn: process.env.CODERADAR_DSN, project: "truecom", environment: process.env.NODE_ENV, release: process.env.RELEASE_SHA, sampleRate: 1.0, // errors always 100% tracesSampleRate: 0.2, // 20% of traces }); // 3. that's it. Errors auto-capture, traces auto-instrument, // W3C tracecontext propagates across outbound fetch / undici. // 4. (optional) Express / Hono middleware import { errorHandler } from "@coderadar/sdk/express"; app.use(errorHandler());
// option A — script tag (autoload, ~12 KB gzipped) <script src="https://cdn.coderadar.app/v1/sdk.js" data-project="truecom" data-env="production" data-release="[email protected]"> </script> // option B — npm package (typed, tree-shakable) // $ pnpm add @coderadar/browser import { init } from "@coderadar/browser"; init({ dsn: "https://[email protected]/12", project: "truecom", environment: "production", release: "[email protected]", }); // captures unhandled errors, unhandled promise rejections, // console errors, and (optionally) fetch breadcrumbs.
# 1. install # $ pip install coderadar # 2. init at process boot import coderadar import os coderadar.init( dsn = os.environ["CODERADAR_DSN"], project = "veritize", environment = os.environ.get("ENV", "dev"), release = os.environ.get("RELEASE_SHA"), sample_rate = 1.0, traces_sample_rate = 0.2, ) # 3. unhandled exceptions auto-capture. # FastAPI / Flask / Django middleware available: from coderadar.fastapi import CodeRadarMiddleware app.add_middleware(CodeRadarMiddleware)
// 1. install // $ go get github.com/RelayOne/coderadar/sdks/go/coderadar // 2. init at main() package main import ( "os" "github.com/RelayOne/coderadar/sdks/go/coderadar" ) func main() { client, _ := coderadar.NewClient(coderadar.Config{ DSN: os.Getenv("CODERADAR_DSN"), Project: "relaygate", Environment: os.Getenv("ENV"), Release: os.Getenv("RELEASE_SHA"), SampleRate: 1.0, TracesSampleRate: 0.2, }) defer client.Flush() // net/http auto-wrap; chi / gin / echo helpers in submodules handler := coderadar.WrapHandler(yourMux) http.ListenAndServe(":8080", handler) }
@coderadar/sdk, @coderadar/browser, coderadar (PyPI), github.com/RelayOne/coderadar/sdks/go/coderadar.
Each SDK ships its own setup page.
Rules and channels. No magic, no inscrutable ML.
Alert rules are explicit: a query, a threshold, a channel. Two kinds: threshold rules (fire when an event count or rate crosses a number) and pattern rules (fire on new fingerprints, regressions, or burn-rate spikes). The rule list is a checklist. The channel list is a checklist. Wire them up in the dashboard or via YAML in the project repo.
CodeRadar vs Sentry vs Datadog — honest table.
CodeRadar is younger, narrower, and free inside the org. Sentry is the gold standard for error tracking; Datadog is broader and pricier. The table below tries not to oversell.
| Capability | CodeRadar | Sentry | Datadog APM |
|---|---|---|---|
| Error tracking | yes | yes | via separate "Error Tracking" SKU |
| Distributed traces (W3C) | yes | yes | yes |
| Real-time SSE feed | yes | live mode in newer plans | yes |
| Source-map auto-resolution | yes | yes | browser only |
| Smart alerting (rules + channels) | yes (slack/email/webhook) | yes (15+ channels) | yes (20+ channels) |
| PagerDuty | roadmap | yes | yes |
| Session replay | roadmap (early-access) | yes | yes (RUM) |
| Self-host (Apache 2.0) | yes (CodeWatch core) | Functional Source License | no |
| Cost inside Goodventures org | $0 / always | Team plan ~$26/mo + per-event | ~$31/host/mo + per-span |
| Auto-fix PRs (AI pipeline) | via CodeWatch core (off by default) | no | no |
| SOC 2 | in progress | yes | yes |
| Maturity | v0.x — early | 12 years | 15+ years |
CodeRadar is replacing Sentry inside our portfolio for one reason: cost-and-control. We are not pretending CodeRadar matches Sentry's depth on day one. We are saying we can get to 80% of the workflow on infrastructure we already operate, charge ourselves nothing, and skip the per-event meter that punishes high-throughput services. If you are not Goodventures, Sentry is still the right call.
CodeRadar fits with the rest of the stack.
Every Goodventures product can stand alone, but the seams between them compound. Here are the four CodeRadar absorbs first. Graceful degradation is the rule — none of these is required.
level:info events, so deployment correlation with errors is a single query.truecom project so settlement health is a first-class alert source.$0 for Goodventures projects. No event meter.
CodeRadar is operated by us, for us. Every product in the portfolio gets a project at no cost. Hard quota per project keeps any one app from drinking the lake; the limits are sized for normal-shaped traffic, not tuned to push you onto a paid tier.
Portfolio internal
The full feature set with no event meter, no per-host fee, and no support tier upsell. Sized for the portfolio, paid for by the portfolio.
- 5M events / month — soft burn-rate alarm at 80%
- 1M traces / month — adaptive sampling kicks in over the cap
- 30-day event retention, 90-day trace retention, 1-year aggregates
- Unlimited projects within the org
- Unlimited members via the Goodventures Clerk session
- Real-time event stream (SSE)
- W3C tracecontext distributed traces
- Source-map auto-resolution
- Smart alerts (Slack, email, webhook)
- Per-project sampling and quotas
- Source code links from stack traces
- Release tagging + regression detection
- API access for ingest + query
- Member-level project access controls
- SOC 2 evidence pack on request in progress
If you are not a Goodventures product, CodeRadar is not currently offered as a paid product. The open CodeWatch core is Apache 2.0 and you can self-host the same pipeline. A managed CodeRadar tier for portfolio adjacent companies (Goodventures alums, partners) is on the roadmap.
Polyglot monorepo. TypeScript at the edge, Python in the middle, TypeScript at the surface.
CodeRadar is built on the open CodeWatch Apache 2.0 core. The data path is intentionally simple: capture at the edge, store in two databases optimized for their workload, surface in a streaming dashboard, route alerts. The optional AI auto-fix pipeline lives in its own Python service so it can scale independently and stay off when not in use.
SDK layer
Per-language clients with a shared wire format. Node + Browser written in TypeScript, Python in pure Python (no C extension), Go in pure Go. All four use the same OTLP-shaped event envelope so the ingest API treats them identically.
Ingest API
Hono on Node. Accepts batched events on POST /v1/events. Writes to ClickHouse via the native binary protocol. Publishes a Redis pub/sub message per accepted event so the dashboard SSE can pick it up. Backpressure-aware with per-project rate buckets.
ClickHouse
Single-table event log keyed on (project_id, timestamp, fingerprint). Columnar, mergeable, queryable in tens of milliseconds for million-row windows. Materialized views for the most common dashboards (top errors, count-per-minute, p95 latency).
PostgreSQL
Metadata. Projects, members, alert rules, releases, comments, saved queries. Postgres because alert evaluation joins these every minute and Postgres is faster than ClickHouse for that shape. Migrations live in sql/migrations/ and run on boot.
Dashboard
Next.js 15 App Router. Streams the live feed over Server-Sent Events, paginates historical queries through a server action that hits ClickHouse directly. Shadcn-style component primitives, no client-side global state framework, JS bundle stays under 180 KB.
Fix pipeline (opt-in)
Optional AI fix pipeline lives in apps/fix-pipeline as a FastAPI service. Triages incoming errors with Claude Haiku, diagnoses with Claude Sonnet, generates three candidate fixes, votes, validates against test runners, and opens a PR via GitHub App. Off by default. Enable per-project.
An error tracker writes a lot more than it reads (most events are never opened). ClickHouse is great at that shape. An alert engine reads a lot more than it writes (every minute, evaluate every rule against the recent window). Postgres is great at that shape. Putting them in one database compromises both. Keeping them separated keeps each in the workload it was built for.
One event, one trace, one breadcrumb. Plain.
CodeRadar's wire format is a strict subset of OpenTelemetry's log-record + span model with a few additions for error-tracker workflows (fingerprint, release, breadcrumbs, user context). Anyone fluent in Sentry's or OTLP's data shapes is at home in five minutes.
// POST /v1/events { "event_id": "ev_01HZRX4D2KQ7", "project": "truecom", "timestamp": "2026-04-26T14:22:08.421Z", "level": "error", // fatal | error | warning | info | debug "environment": "production", "release": "[email protected]", "runtime": { "name": "node", "version": "22.5.0" }, "exception": { "type": "TypeError", "value": "Cannot read properties of undefined (reading 'amount')", "stacktrace": [ { "file": "apps/dashboard/src/Errors.tsx", "line": 284, "function": "renderRow" }, // ... more frames ] }, "user": { "id": "u_RR91xK", "email_hash": "sha256:..." }, "trace_id": "b7f3a44d8e21c3d201", "span_id": "8e21c3d201", "breadcrumbs": [ /* up to 100 — see Breadcrumb tab */ ], "tags": { "region": "us-central1", "customer": "acme" }, "fingerprint": [ "TypeError", "Errors.tsx", "renderRow" ] // optional override }
// trace = collection of spans sharing trace_id { "trace_id": "b7f3a44d8e21c3d201", "spans": [ { "span_id": "5a2c", "parent_id": null, "name": "GET /api/billing/invoices", "start": "...:08.150Z", "end": "...:08.421Z", "attributes": { "http.status_code": 500, "http.route": "/api/billing/invoices" } }, { "span_id": "5a2d", "parent_id": "5a2c", "name": "db.query: select * from invoices...", "start": "...:08.180Z", "end": "...:08.395Z", "attributes": { "db.system": "postgresql", "db.statement": "SELECT ..." } }, { "span_id": "5a2e", "parent_id": "5a2c", "name": "render: dashboard.Errors", "start": "...:08.398Z", "end": "...:08.421Z", "events": [ { "name": "exception", "event_id": "ev_01HZRX4D2KQ7" } ] } ] }
// up to 100 breadcrumbs are attached to each captured event [ { "t": "...:08.041Z", "category": "navigation", "message": "/dashboard → /dashboard/billing" }, { "t": "...:08.085Z", "category": "http", "data": { "method": "GET", "url": "/api/billing/invoices", "status": 500 } }, { "t": "...:08.140Z", "category": "console", "level": "warn", "message": "Falling back to cached invoices" }, { "t": "...:08.205Z", "category": "ui.click", "data": { "target": "button.retry", "text": "Retry" } }, { "t": "...:08.298Z", "category": "http", "data": { "method": "GET", "url": "/api/billing/invoices", "status": 500 } }, { "t": "...:08.420Z", "category": "render", "message": "Errors.tsx unmount → mount with empty rows" } ] // Categories: navigation, http, console, ui.click, ui.input, render, custom.*
# YAML — checked into the project repo, applied by `coderadar alerts apply` # Or configure in the dashboard at /alerts/new version: 1 project: truecom rules: - name: fatal_in_production when: level:fatal env:production threshold: count > 0 in 1m channels: [slack-prod, email-eric] cooldown: 5m - name: spike_any when: level:error threshold: count > 50 in 5m group_by: [project] channels: [slack-prod] - name: new_fingerprint when: fingerprint:new env:production channels: [slack-prod] channels: - id: slack-prod type: slack webhook: ${SLACK_WEBHOOK_URL} - id: email-eric type: email to: [[email protected]]
/v1/otlp for non-CodeRadar SDKs.
Frameworks. Logging. Custom captures.
If your framework is not auto-instrumented, you can capture errors with captureException(). If you have a logger, the SDK exposes a transport for popular ones (pino, winston, structlog, zap). Browser-side fetch wraps cleanly. Below: the patterns we hit most often inside the portfolio.
// instrumentation.ts — Next.js 15 App Router export async function register() { if (process.env.NEXT_RUNTIME === "nodejs") { const { init } = await import("@coderadar/sdk"); init({ dsn: process.env.CODERADAR_DSN, project: "truecom", release: process.env.VERCEL_GIT_COMMIT_SHA, }); } } // app/global-error.tsx — Next 15 server error boundary "use client"; import { captureException } from "@coderadar/sdk"; export default function GlobalError({ error }) { captureException(error); return <html>...</html>; }
import { Hono } from "hono"; import { honoMiddleware } from "@coderadar/sdk/hono"; const app = new Hono(); app.use("*", honoMiddleware({ project: "relayone", release: process.env.RELEASE_SHA, })); app.get("/api/me", async (c) => { const u = await getUser(c); // throws? auto-captured. return c.json(u); });
from fastapi import FastAPI from coderadar.fastapi import CodeRadarMiddleware import coderadar import os coderadar.init( dsn=os.environ["CODERADAR_DSN"], project="veritize", release=os.environ.get("RELEASE_SHA"), ) app = FastAPI() app.add_middleware(CodeRadarMiddleware) # manual capture inside a handler from coderadar import capture_exception, capture_message, set_user @app.get("/billing/{id}") async def billing(id: str): try: return await get_invoice(id) except InvoiceMissing as e: capture_exception(e, tags={"invoice_id": id}) raise
package main import ( "github.com/go-chi/chi/v5" "github.com/RelayOne/coderadar/sdks/go/coderadar" "github.com/RelayOne/coderadar/sdks/go/coderadar/chimid" ) func main() { coderadar.NewClient(coderadar.Config{ DSN: os.Getenv("CODERADAR_DSN"), Project: "relaygate", }) r := chi.NewRouter() r.Use(chimid.Middleware()) // captures panics + 500s r.Get("/healthz", healthz) http.ListenAndServe(":8080", r) }
// every SDK exposes capture* helpers // node / browser import { captureException, captureMessage, setUser, addBreadcrumb } from "@coderadar/sdk"; setUser({ id: user.id, segment: user.tier }); addBreadcrumb({ category: "checkout", message: "opened cart" }); try { await finalizeCheckout(cart); } catch (err) { captureException(err, { tags: { stage: "checkout" } }); throw err; } captureMessage("Inventory desync detected", { level: "warning" });
The shape of one observability plane.
Every cell below is a feature that ships in the box, with the file path or service name where it lives. Roadmap items are flagged. No magic, no reading-tea-leaves about what is and isn't in v0.
Ingest endpoint
OTLP-shape, batched, idempotent.
Trace ingest
OTLP /v1/traces.
Source-map upload
POST /v1/sourcemaps.
Release tagging
POST /v1/releases.
Fingerprinting
Stable, type+frame-based.
Dedup
ClickHouse ReplacingMergeTree.
Live SSE
Per-project topic, sub-second.
Search query lang
field:value op:val + lucene-ish.
Saved queries
Per-user, per-project.
Pinned queries
Streaming, dashboard widget.
Breadcrumbs
Up to 100, configurable.
User context
id + email_hash + tier.
Tags / attributes
Per-event arbitrary k/v.
Releases
SHA, environment, deployed_at.
Regression detect
Was-resolved + new-event.
Alert rules
Threshold + pattern.
Slack channel
Webhook + block-kit body.
Email channel
Resend + templated body.
Webhook channel
HTTP POST, retry+jitter.
PagerDuty roadmap
Events API v2.
Quota engine
Per-project hard + soft.
Sampling
Adaptive + manual.
Auth (Clerk)
Org + projects + members.
REST API
Read-only ingest + query.
Session replay roadmap
DOM snapshot diff stream.
AI fix pipeline
Triage → diagnose → vote → PR.
Self-host (Helm)
Compose + Helm chart.
Audit log
Who-did-what on rules + projects.
A real example of CodeRadar set up across the portfolio.
Everything below is the actual configuration the Goodventures portfolio uses — pasted from the project repos with secrets redacted. Same pattern for every product: SDK at boot, environment per deploy target, release tagged on each push, alert rules in .coderadar/alerts.yaml, source maps uploaded by CI.
// apps/portal/instrumentation.ts import { init } from "@coderadar/sdk"; export async function register() { if (process.env.NEXT_RUNTIME === "nodejs") { init({ dsn: process.env.CODERADAR_DSN_TRUECOM, project: "truecom", environment: process.env.NODE_ENV ?? "development", release: process.env.RELEASE_SHA, tracesSampleRate: 0.2, }); } }
// cmd/relaygate/main.go import "github.com/RelayOne/coderadar/sdks/go/coderadar" func main() { cr, _ := coderadar.NewClient(coderadar.Config{ DSN: os.Getenv("CODERADAR_DSN_RELAYGATE"), Project: "relaygate", Environment: os.Getenv("ENV"), Release: buildVersion + "@" + buildCommit, SampleRate: 1.0, TracesSampleRate: 0.2, }) defer cr.Flush() // wraps every HTTP handler with capture-on-panic + 500-detect handler := coderadar.WrapHandler(router) http.ListenAndServe(":8080", handler) }
# apps/api/src/main.py import coderadar from coderadar.fastapi import CodeRadarMiddleware from fastapi import FastAPI coderadar.init( dsn=os.environ["CODERADAR_DSN_VERITIZE"], project="veritize", environment=os.environ.get("ENV"), release=os.environ.get("RELEASE_SHA"), traces_sample_rate=0.2, ) app = FastAPI() app.add_middleware(CodeRadarMiddleware) # cron worker — manual capture for non-HTTP runs from coderadar import capture_exception, set_tag def drift_scan_job(): set_tag("job", "drift_scan") try: run_drift_scan() except Exception as e: capture_exception(e) raise
version: 1 project: truecom rules: - name: fatal_in_production when: level:fatal env:production threshold: count > 0 in 1m channels: [slack-prod, email-eric] cooldown: 5m - name: spike_5x when: level:error env:production threshold: rate > baseline * 5 in 5m channels: [slack-prod] - name: new_fingerprint when: fingerprint:new env:production channels: [slack-prod] - name: regression when: fingerprint.was_resolved == true channels: [slack-prod, email-eric] channels: - id: slack-prod type: slack webhook: ${SLACK_WEBHOOK_URL} - id: email-eric type: email to: [[email protected]]
# cloudbuild.yaml — runs after the deploy step - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim' entrypoint: 'bash' args: - '-c' - | pnpm dlx @coderadar/cli releases create \ --project=truecom \ --release=truecom@$SHORT_SHA \ --commit=$COMMIT_SHA pnpm dlx @coderadar/cli sourcemaps upload \ --project=truecom \ --release=truecom@$SHORT_SHA \ --rewrite \ --strip-common-prefix \ dist/static/js/ pnpm dlx @coderadar/cli alerts apply \ --file=.coderadar/alerts.yaml
From error fired to fingerprint resolved.
An error doesn't disappear when an alert fires. It travels through a small but explicit lifecycle so the same fingerprint doesn't burn the on-call twice. Below: the eight states the system understands, and what triggers each transition.
If your project doesn't want triage, you can stop after step 3. If you want to skip alert ack, default cooldowns work. The lifecycle is a tool, not a process you're forced to run.
Environment variables and DSN format.
CodeRadar SDKs read configuration from explicit init params or environment variables. The DSN encodes the project, ingest host, and public token. Tokens are scoped to a project + an ingest write capability — never grant query access.
// DSN — public token for write-only ingest https://PUBLIC_KEY@ingest.coderadar.app/PROJECT_ID // example https://[email protected]/12 // the public key is safe to expose in browser bundles. // it is per-project, write-only, and rate-limited per origin. // rotate any time at app.coderadar.app/settings/keys. // for stricter setups, use the IP-allowlisted "server-only" DSN // which won't accept events without a Bearer token cookie. https://PUBLIC_KEY:SECRET@ingest.coderadar.app/PROJECT_ID?mode=server
# every SDK reads these env vars by default CODERADAR_DSN="https://[email protected]/12" CODERADAR_PROJECT="truecom" # or set in init() — env var wins CODERADAR_ENVIRONMENT="production" # dev | staging | production | preview-* | ... CODERADAR_RELEASE="[email protected]" # SHA or semver tag CODERADAR_SAMPLE_RATE="1.0" # 0.0–1.0 — errors CODERADAR_TRACES_SAMPLE_RATE="0.2" # 0.0–1.0 — traces CODERADAR_DEBUG="false" # SDK self-logging CODERADAR_BUFFER_SIZE="1048576" # bytes, server SDKs only CODERADAR_FLUSH_INTERVAL="5000" # ms # dual-accept legacy CODEWATCH_* env vars (90-day window) CODEWATCH_DSN=# still accepted; logs deprecation warning at boot
# the coderadar CLI $ pnpm add -g @coderadar/cli # list projects you can see $ coderadar projects list # tail events from one project $ coderadar tail --project=truecom --level=error # upload a sourcemap manually $ coderadar sourcemaps upload \ --project=truecom \ [email protected] \ --file=dist/static/js/main.abc123.js.map # apply alert rules from a YAML file $ coderadar alerts apply --file=.coderadar/alerts.yaml # open a project in the dashboard $ coderadar open truecom
@coderadar/cli. Source at apps/cli in the CodeWatch repo.
Common questions, honest answers.
For Goodventures-internal use, yes — that is the entire reason it exists. For everyone else, Sentry is more mature, deeper on session replay, deeper on integrations. We are not pretending otherwise.
CodeWatch is the open-source error-tracking + AI-fix-pipeline core. CodeRadar is the operating shell on top of it: domain, branding, portfolio-aware project model, alerting workflows. Same code path; different presentation.
Because the portfolio is the customer. The infrastructure is shared, the operations team is shared, the storage is shared. Adding a per-event meter on top would be us paying ourselves to count events. We just put a hard quota on each project instead.
ClickHouse handles billions of events per day per cluster. The bottleneck is the ingest API's egress to ClickHouse, which is horizontally scalable. Today we run one ingest pod and one Postgres; both scale before quota turns into a real problem.
GCP us-central1 by default. EU and BC-Canadian regions on the roadmap (BC via the Heroa substrate). No data leaves the cluster except via webhook/email channels you configured.
Roadmap. The CodeWatch core is Apache 2.0 today and you can self-host. A managed CodeRadar tier for portfolio-adjacent companies (alums, partners) is being scoped, but the priority is portfolio-internal stability first.
SDKs ship with a default scrub list (auth headers, password fields, common PII patterns). The scrub list is overridable per project. Receipts are stored hashed, not in plaintext. Full posture in /security.
SDKs have a 1 MB / 5-minute local buffer with on-disk persistence (server SDKs only). Browser SDKs drop oldest events first. Either way the application keeps running — capture is fire-and-forget by design.
Ship the SDK today. See errors by tomorrow.
Five lines in your bootstrap. The Goodventures Clerk session takes you straight into the dashboard. If you are setting up a new project, the quickstart walks you through DSN provisioning, source-map upload, and the first alert in under five minutes.