Skip to content

refactor: update ch reads#3958

Merged
chronark merged 17 commits intomainfrom
update-ch-reads
Sep 17, 2025
Merged

refactor: update ch reads#3958
chronark merged 17 commits intomainfrom
update-ch-reads

Conversation

@ogzhanolguncu
Copy link
Contributor

@ogzhanolguncu ogzhanolguncu commented Sep 12, 2025

What does this PR do?

This PR updates table names to accommodate CH structure changes. Also removed unused CH queries.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Chore (refactoring code, technical debt, workflow improvements)
  • Enhancement (small improvements)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How should this be tested?

  • Make sure every chart works as before
  • Make sure every logs page works as before
  • Make sure billing updates correctly, because we updated that as well.

Checklist

Required

  • Filled out the "How to test" section in this PR
  • Read Contributing Guide
  • Self-reviewed my own code
  • Commented on my code in hard-to-understand areas
  • Ran pnpm build
  • Ran pnpm fmt
  • Checked for warnings, there are none
  • Removed all console.logs
  • Merged the latest changes from main onto my branch with git pull origin main
  • My changes don't cause any responsiveness issues

Appreciated

  • If a UI change was made: Added a screen recording or screenshots to this PR
  • Updated the Unkey Docs if changes were necessary

Summary by CodeRabbit

  • Bug Fixes

    • Region column in Ratelimit Logs now shows the correct region value and label (replacing "colo").
  • Chores

    • Upgraded underlying analytics, verifications, billing, rate-limit, and request logging sources to newer v2/default datasets for more consistent, up-to-date reporting (no user action required).

@changeset-bot
Copy link

changeset-bot bot commented Sep 12, 2025

⚠️ No Changeset found

Latest commit: 659c38f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Sep 12, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
dashboard Ready Ready Preview Comment Sep 17, 2025 11:38am
1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
engineering Ignored Ignored Preview Sep 17, 2025 11:38am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 12, 2025

📝 Walkthrough

Walkthrough

Migrated many ClickHouse queries and timeseries intervals from legacy schemas to default v2 tables; renamed ratelimit log field coloregion across backend and dashboard UI; removed an obsolete active_keys module; test harness now generates workspace slugs dynamically. Only RatelimitLog’s field rename altered an exported type.

Changes

Cohort / File(s) Summary
Ratelimits data sources & field rename
internal/clickhouse/src/ratelimits.ts, apps/dashboard/app/(app)/ratelimits/[namespaceId]/logs/components/table/logs-table.tsx
Switched ratelimit interval/latency/raw tables to default.*_v2; updated joins to default.api_requests_raw_v2; renamed output field coloregion and adjusted UI rendering to log.region.
Logs data source
internal/clickhouse/src/logs.ts
Switched log reads to default.api_requests_raw_v2; minor CASE/formatting tweaks only.
Verifications sources & intervals
internal/clickhouse/src/verifications.ts, internal/clickhouse/src/latest_verifications.ts, internal/clickhouse/src/keys/keys.ts, apps/dashboard/lib/trpc/routers/api/keys/query-api-keys/get-all-keys.ts
Pointed reads/inserts and first-CTE sources to default.key_verifications_raw_v2; updated timeseries interval tables to default.*_v2; preserved query logic and signatures.
Active keys intervals & removal
internal/clickhouse/src/keys/active_keys.ts, internal/clickhouse/src/active_keys.ts
Updated ACTIVE_KEYS_INTERVALS to default.*_v2 tables; removed legacy module exporting getActiveKeysPerHour/Day/Month.
Billing sources
internal/clickhouse/src/billing.ts
Switched monthly billable ratelimits/verifications sources to default.*_v2 (schema/version updates).
Success metric source
internal/clickhouse/src/success.ts
Switched to default.active_workspaces_per_month_v2; minor whitespace normalization.
Test harness slug generation
apps/api/src/pkg/testutil/harness.ts
Replaced hard-coded workspace slugs with newId("test") generated slugs.

Sequence Diagram(s)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • perkinsjr
  • mcstepp
  • chronark

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description includes a short summary, type, testing guidance, and a completed checklist, but it does not fully follow the repository template: it omits the required "Fixes #..." issue reference and lacks specific motivation, dependency/migration details, and explicit mention of notable schema changes (e.g., the colo→region rename) and removed queries. Because the template asks for an issue link and concrete context for tracking and safe rollout, the description is incomplete and fails the template validation. Please add a linked issue ("Fixes #") or create one if none exists, expand the "What does this PR do?" section to list the specific ClickHouse tables and fields changed (including the colo→region rename) and any removed queries, and document any required migration/backfill steps or dependencies. Also update the "How should this be tested?" section with concrete reproduction steps and expected results for charts, logs pages, and billing (and note any limitations testing locally), and mark the documentation checkbox if docs need updating.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title "refactor: update ch reads" is concise and accurately reflects the primary change in the diff (refactoring ClickHouse read queries and updating table names/reads); it communicates the intent as a non-functional refactor. The only minor issue is the abbreviation "ch" which could be expanded for clarity to "ClickHouse" for readers unfamiliar with the shorthand.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch update-ch-reads

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel vercel bot temporarily deployed to Preview – dashboard September 12, 2025 12:13 Inactive
@ogzhanolguncu
Copy link
Contributor Author

Please, disregard anything related to ratelimit latencies for now. It will be updated in the next iterations.

@ogzhanolguncu ogzhanolguncu marked this pull request as ready for review September 12, 2025 12:49
@vercel vercel bot temporarily deployed to Preview – dashboard September 12, 2025 12:51 Inactive
@github-actions
Copy link
Contributor

github-actions bot commented Sep 12, 2025

Thank you for following the naming conventions for pull request titles! 🙏

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
internal/clickhouse/src/keys/keys.ts (1)

270-279: Confirm v2 raw schema parity (time/outcome/tags).

filtered_keys now reads from default.key_verifications_raw_v2. Ensure the v2 table exposes time, key_id, request_id, tags, outcome with compatible types. If time is DateTime64, consider casting params (fromUnixTimestamp64Milli) for strict typing.

internal/clickhouse/src/logs.ts (1)

211-257: Replace metrics._v1 timeseries tables with default._v2

INTERVALS in internal/clickhouse/src/logs.ts still point at metrics.api_requests_per_v1 while the repo contains default.api_requests_per_v2 rollups (migrations and other internal/clickhouse code already use default.*_v2). Update INTERVALS to the v2 tables to avoid broken charts.

File: internal/clickhouse/src/logs.ts (INTERVALS, ~lines 211–257)

-    table: "metrics.api_requests_per_minute_v1",
+    table: "default.api_requests_per_minute_v2",
@@
-    table: "metrics.api_requests_per_minute_v1",
+    table: "default.api_requests_per_minute_v2",
@@
-    table: "metrics.api_requests_per_minute_v1",
+    table: "default.api_requests_per_minute_v2",
@@
-    table: "metrics.api_requests_per_hour_v1",
+    table: "default.api_requests_per_hour_v2",
@@
-    table: "metrics.api_requests_per_hour_v1",
+    table: "default.api_requests_per_hour_v2",
@@
-    table: "metrics.api_requests_per_hour_v1",
+    table: "default.api_requests_per_hour_v2",
@@
-    table: "metrics.api_requests_per_hour_v1",
+    table: "default.api_requests_per_hour_v2",
@@
-    table: "metrics.api_requests_per_day_v1",
+    table: "default.api_requests_per_day_v2",
internal/clickhouse/src/verifications.ts (1)

181-184: Return shape bug: logs returns the wrapper, not rows.

You await the queries but return logs: clickhouseResults instead of logs: clickhouseResults.val. This is inconsistent with totalCount handling and likely breaks callers.

-    return {
-      logs: clickhouseResults,
-      totalCount: totalResults.val ? totalResults.val[0].total_count : 0,
-    };
+    return {
+      logs: clickhouseResults.val ?? [],
+      totalCount: totalResults.val ? totalResults.val[0].total_count : 0,
+    };
internal/clickhouse/src/ratelimits.ts (2)

226-234: Table switch for last-used looks good; verify multiSearchAny index coverage.

Confirm default.ratelimits_last_used_v2 has an index/projection supporting multiSearchAny(identifier, ...) to avoid full scans on large namespaces.


355-404: Data source migrations LGTM; add workspace filter to metrics join for safety.

The LEFT JOIN subquery already filters by workspace_id; keep it, but consider also AND m.workspace_id = fr.workspace_id in the ON to prevent accidental cross-tenant joins if request_id ever clashes.

-) m ON fr.request_id = m.request_id
+) m ON fr.request_id = m.request_id AND m.workspace_id = fr.workspace_id

Also applies to: 412-418

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10f390e and cb866c3.

📒 Files selected for processing (12)
  • apps/dashboard/app/(app)/ratelimits/[namespaceId]/logs/components/table/logs-table.tsx (1 hunks)
  • apps/dashboard/lib/trpc/routers/api/keys/query-api-keys/get-all-keys.ts (1 hunks)
  • internal/clickhouse/src/active_keys.ts (0 hunks)
  • internal/clickhouse/src/billing.ts (2 hunks)
  • internal/clickhouse/src/keys/active_keys.ts (1 hunks)
  • internal/clickhouse/src/keys/keys.ts (1 hunks)
  • internal/clickhouse/src/latest_verifications.ts (1 hunks)
  • internal/clickhouse/src/logs.ts (4 hunks)
  • internal/clickhouse/src/ratelimits.ts (14 hunks)
  • internal/clickhouse/src/requests.ts (1 hunks)
  • internal/clickhouse/src/success.ts (1 hunks)
  • internal/clickhouse/src/verifications.ts (5 hunks)
💤 Files with no reviewable changes (1)
  • internal/clickhouse/src/active_keys.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: chronark
PR: unkeyed/unkey#3161
File: go/pkg/clickhouse/schema/databases/001_verifications/002_raw_key_verifications_v1.sql:31-33
Timestamp: 2025-04-22T14:40:51.459Z
Learning: The ClickHouse table schemas in the codebase mirror the production environment and cannot be modified directly in PRs without careful migration planning.
📚 Learning: 2024-10-20T07:05:55.471Z
Learnt from: chronark
PR: unkeyed/unkey#2294
File: apps/api/src/pkg/keys/service.ts:268-271
Timestamp: 2024-10-20T07:05:55.471Z
Learning: In `apps/api/src/pkg/keys/service.ts`, `ratelimitAsync` is a table relation, not a column selection. When querying, ensure that table relations are included appropriately, not as columns.

Applied to files:

  • internal/clickhouse/src/ratelimits.ts
🧬 Code graph analysis (1)
apps/dashboard/app/(app)/ratelimits/[namespaceId]/logs/components/table/logs-table.tsx (1)
internal/clickhouse/src/logs.ts (1)
  • log (24-38)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test Go API Local / Test
  • GitHub Check: Build / Build
  • GitHub Check: Test API / API Test Local
🔇 Additional comments (13)
internal/clickhouse/src/success.ts (1)

11-17: LGTM: migrated to v2 source

Source table switch to default.active_workspaces_per_month_v2 looks consistent; ordering and schema mapping stay intact.

apps/dashboard/lib/trpc/routers/api/keys/query-api-keys/get-all-keys.ts (1)

113-118: LGTM: tag filter now reads from v2

Switch to default.key_verifications_raw_v2 aligns with the broader migration. Please confirm tags column exists unchanged in v2 for this query.

internal/clickhouse/src/latest_verifications.ts (1)

19-22: LGTM: verifications source updated to v2

Region/tags selected from default.key_verifications_raw_v2; schema unchanged.

internal/clickhouse/src/logs.ts (2)

136-138: LGTM: total count now from v2 raw

Counts sourced from default.api_requests_raw_v2; paramization intact.


159-161: LGTM: logs page now reads from v2 raw

Select list and filters unchanged; ordering by time DESC preserved.

internal/clickhouse/src/keys/active_keys.ts (1)

65-78: LGTM: ACTIVE_KEYS interval sources migrated to v2

All per-minute/hour/day/month sources now default.*_v2; query builder and casts remain consistent.

Also applies to: 81-104, 107-137

internal/clickhouse/src/verifications.ts (4)

8-8: Insert target moved to default.key_verifications_raw_v2 — check column types match.

Double-check the raw v2 table column types (especially time and identity_id) align with the insert schema to avoid implicit casts.


69-71: Type alias change is fine.

Switching to a type alias with an index signature is appropriate for dynamic param extension.


264-336: Timeseries tables migrated to v2 — confirm retention and materialization windows.

Ensure the v2 per_minute/hour/day/month tables have identical retention/materialization to v1 to avoid gaps during charting.


149-150: ```shell
#!/bin/bash
set -euo pipefail
FILE="internal/clickhouse/src/verifications.ts"

echo "PWD: $(pwd)"
echo
echo "---- list internal/clickhouse/src ----"
ls -la internal/clickhouse/src || true
echo

if [ -f "$FILE" ]; then
echo "---- show $FILE (lines 1-400) ----"
sed -n '1,400p' "$FILE" || true
echo
echo "---- show $FILE (lines 140-170) ----"
sed -n '140,170p' "$FILE" || true
else
echo "MISSING: $FILE"
fi

echo
echo "---- repo search for relevant patterns ----"
PATTERNS=(
"key_verifications_raw_v2"
"default.key_verifications_raw_v2"
"baseConditions"
"fromUnixTimestamp64Milli"
"fromUnixTimestamp64"
"fromUnixTimestamp"
"DateTime64"
"DateTime("
"UInt64"
"{startTime"
"{endTime"
"startTime:"
"endTime:"
"time BETWEEN"
"workspace_id ="
"key_space_id ="
"key_id ="
)

if command -v rg >/dev/null 2>&1; then
for p in "${PATTERNS[@]}"; do
echo "---- rg for: $p ----"
rg -n -S -C3 "$p" || true
done
else
for p in "${PATTERNS[@]}"; do
echo "---- grep for: $p ----"
grep -RIn --line-number -C3 --exclude-dir=.git "$p" . || true
done
fi

echo
echo "---- done ----"


</blockquote></details>
<details>
<summary>internal/clickhouse/src/ratelimits.ts (3)</summary><blockquote>

`290-290`: **Public contract change: colo → region.**

Backend type updated; ensure all downstream consumers use region. The dashboard table was updated per PR notes; verify any API clients too.

---

`618-643`: **Overview query looks correct; ordering guarded.**

Allowed-columns map prevents ORDER BY injection; good. No action needed.



Also applies to: 652-656

---

`702-746`: **Latency intervals moved to v2 — acknowledged per PR note.**

Per the author’s comment, skipping deep review of latency changes now. Surfaces look consistent with other v2 migrations.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Copy link
Collaborator

@chronark chronark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code looks good, I haven't ran it in the dashboard yet to see if everything loads though

@ogzhanolguncu
Copy link
Contributor Author

@chronark I couldn't test the billing properly, could you make sure for me? It acts weird for me locally

Copy link
Collaborator

Yeah I’ll do a proper test on monday

@vercel vercel bot temporarily deployed to Preview – dashboard September 12, 2025 14:47 Inactive
@vercel vercel bot temporarily deployed to Preview – dashboard September 12, 2025 15:23 Inactive
@vercel vercel bot temporarily deployed to Preview – dashboard September 17, 2025 10:21 Inactive
@chronark
Copy link
Collaborator

I need to clean this up cause it does writes too
shouldn't be too hard

@vercel vercel bot temporarily deployed to Preview – engineering September 17, 2025 11:21 Inactive
@chronark
Copy link
Collaborator

ok this is reverted, now it's actually just changing reads

@ogzhanolguncu @perkinsjr please sanity check me when you have some time
no rush

@vercel vercel bot temporarily deployed to Preview – dashboard September 17, 2025 11:26 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/api/src/pkg/testutil/harness.ts (1)

274-279: Same concern for user workspace slug

Apply the same URL-safe pattern to avoid underscore/mixed-case issues and update any tests that relied on "user-workspace".

-      slug: newId("test"),
+      // URL-safe, kebab-case; keeps human prefix for readability
+      slug: `user-${newId("test").split("_")[1]}`,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20b53da and eb6fb5b.

📒 Files selected for processing (1)
  • apps/api/src/pkg/testutil/harness.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: chronark
PR: unkeyed/unkey#3958
File: internal/clickhouse/src/requests.ts:7-8
Timestamp: 2025-09-12T13:25:41.814Z
Learning: In the ClickHouse v2 table migration, the location field was renamed from `colo` to `region` across all tables including `default.api_requests_raw_v2`. The zod insert schemas must be updated accordingly to avoid runtime insert failures.
Learnt from: chronark
PR: unkeyed/unkey#3161
File: go/pkg/clickhouse/schema/databases/001_verifications/002_raw_key_verifications_v1.sql:31-33
Timestamp: 2025-04-22T14:40:51.459Z
Learning: The ClickHouse table schemas in the codebase mirror the production environment and cannot be modified directly in PRs without careful migration planning.
📚 Learning: 2025-08-21T12:37:40.996Z
Learnt from: Flo4604
PR: unkeyed/unkey#3821
File: apps/dashboard/lib/trpc/routers/key/updateRootKeyPermissions.ts:74-74
Timestamp: 2025-08-21T12:37:40.996Z
Learning: Root keys in Unkey have two workspace fields: `workspaceId` (always set to env().UNKEY_WORKSPACE_ID for the Unkey workspace that owns the key) and `forWorkspaceId` (set to ctx.workspace.id for the user's workspace that the key is for). When querying root keys, the system filters by forWorkspaceId to get keys for the current user's workspace, but the returned rootKey.workspaceId is always the Unkey workspace ID.

Applied to files:

  • apps/api/src/pkg/testutil/harness.ts
🧬 Code graph analysis (1)
apps/api/src/pkg/testutil/harness.ts (1)
internal/id/src/generate.ts (1)
  • newId (35-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Test Go API Local / Test
  • GitHub Check: Test Packages / Test
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Build / Build
🔇 Additional comments (1)
apps/api/src/pkg/testutil/harness.ts (1)

254-259: Dynamic slug is good for test isolation — verify slug format & consumers

File: apps/api/src/pkg/testutil/harness.ts (lines 254-259)

    const unkeyWorkspace: Workspace = {
      id: newId("test"),
      name: "unkey",
      slug: newId("test"),
      orgId: newId("test"),
      plan: "enterprise",

Switching to newId("test") removes hard-coded collisions but newId yields test_<b58> (contains an underscore and mixed-case). If slug validators or URL routes assume kebab-case this can break; tests/fixtures referencing "unkey-workspace" will fail.

Consider emitting a URL-safe, kebab-case slug while keeping a human prefix:

-      slug: newId("test"),
+      // URL-safe, kebab-case; keeps human prefix for readability
+      slug: `unkey-${newId("test").split("_")[1]}`,

Repo search attempt returned "No files were searched" (rg skipped files), so I couldn't confirm consumers or hard-coded fixtures — re-run locally with:

rg -n --hidden -uu --fixed-strings -S 'unkey-workspace|user-workspace'
rg -n -C2 -uu -S '\bslug\b.*(zod|regex|pattern|varchar|check|constraint|slugify)'

@vercel vercel bot temporarily deployed to Preview – dashboard September 17, 2025 11:38 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
internal/clickhouse/src/ratelimits.ts (2)

702-746: Consistency: use singular units in LATENCY_INTERVALS too (optional).

Not a functional bug here because you map to singular before SQL, but normalizing reduces cognitive overhead and prevents regressions.

   fiveMinutes: {
-    table: "default.ratelimits_identifier_latency_stats_per_minute_v2",
-    step: "MINUTES",
+    table: "default.ratelimits_identifier_latency_stats_per_minute_v2",
+    step: "MINUTE",
     stepSize: 5,
   },
   fifteenMinutes: {
-    table: "default.ratelimits_identifier_latency_stats_per_minute_v2",
-    step: "MINUTES",
+    table: "default.ratelimits_identifier_latency_stats_per_minute_v2",
+    step: "MINUTE",
     stepSize: 15,
   },
   thirtyMinutes: {
-    table: "default.ratelimits_identifier_latency_stats_per_minute_v2",
-    step: "MINUTES",
+    table: "default.ratelimits_identifier_latency_stats_per_minute_v2",
+    step: "MINUTE",
     stepSize: 30,
   },
   twoHours: {
-    table: "default.ratelimits_identifier_latency_stats_per_hour_v2",
-    step: "HOURS",
+    table: "default.ratelimits_identifier_latency_stats_per_hour_v2",
+    step: "HOUR",
     stepSize: 2,
   },
   fourHours: {
-    table: "default.ratelimits_identifier_latency_stats_per_hour_v2",
-    step: "HOURS",
+    table: "default.ratelimits_identifier_latency_stats_per_hour_v2",
+    step: "HOUR",
     stepSize: 4,
   },
   sixHours: {
-    table: "default.ratelimits_identifier_latency_stats_per_hour_v2",
-    step: "HOURS",
+    table: "default.ratelimits_identifier_latency_stats_per_hour_v2",
+    step: "HOUR",
     stepSize: 6,
   },

51-71: Blocker: plural INTERVAL units will break createTimeseriesQuery.

createTimeseriesQuery injects interval.step verbatim into INTERVAL … ${interval.step}; ClickHouse expects singular units (MINUTE/HOUR). Entries using "MINUTES"/"HOURS" will error at runtime. Normalize to singular or map before SQL generation.

Apply:

   fiveMinutes: {
-    table: "default.ratelimits_per_minute_v2",
-    step: "MINUTES",
+    table: "default.ratelimits_per_minute_v2",
+    step: "MINUTE",
     stepSize: 5,
   },
   fifteenMinutes: {
-    table: "default.ratelimits_per_minute_v2",
-    step: "MINUTES",
+    table: "default.ratelimits_per_minute_v2",
+    step: "MINUTE",
     stepSize: 15,
   },
   thirtyMinutes: {
-    table: "default.ratelimits_per_minute_v2",
-    step: "MINUTES",
+    table: "default.ratelimits_per_minute_v2",
+    step: "MINUTE",
     stepSize: 30,
   },
   twoHours: {
-    table: "default.ratelimits_per_hour_v2",
-    step: "HOURS",
+    table: "default.ratelimits_per_hour_v2",
+    step: "HOUR",
     stepSize: 2,
   },
   fourHours: {
-    table: "default.ratelimits_per_hour_v2",
-    step: "HOURS",
+    table: "default.ratelimits_per_hour_v2",
+    step: "HOUR",
     stepSize: 4,
   },
   sixHours: {
-    table: "default.ratelimits_per_hour_v2",
-    step: "HOURS",
+    table: "default.ratelimits_per_hour_v2",
+    step: "HOUR",
     stepSize: 6,
   },

Also applies to: 73-101

🧹 Nitpick comments (1)
internal/clickhouse/src/ratelimits.ts (1)

355-355: Reads on v2 look good; tighten JOIN to prevent rare cross‑workspace collisions.

Tables migrated to v2 and region selected—good. To be defensive, join on both request_id and workspace_id (and select it in the subquery) to avoid any theoretical request_id collision.

 SELECT
     fr.request_id,
@@
-    m.user_agent,
-    m.region
+    m.user_agent,
+    m.region
 FROM filtered_ratelimits fr
 LEFT JOIN (
     SELECT
-        request_id,
+        request_id,
+        workspace_id,
         host,
         method,
         path,
@@
-        user_agent,
-        region
+        user_agent,
+        region
     FROM default.api_requests_raw_v2
     WHERE workspace_id = {workspaceId: String}
         AND time BETWEEN {startTime: UInt64} AND {endTime: UInt64}
 ) m ON fr.request_id = m.request_id
+    AND fr.workspace_id = m.workspace_id

Also applies to: 382-383, 385-399, 412-412

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb6fb5b and 659c38f.

📒 Files selected for processing (1)
  • internal/clickhouse/src/ratelimits.ts (13 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: chronark
PR: unkeyed/unkey#3958
File: internal/clickhouse/src/requests.ts:7-8
Timestamp: 2025-09-12T13:25:41.814Z
Learning: In the ClickHouse v2 table migration, the location field was renamed from `colo` to `region` across all tables including `default.api_requests_raw_v2`. The zod insert schemas must be updated accordingly to avoid runtime insert failures.
Learnt from: chronark
PR: unkeyed/unkey#3161
File: go/pkg/clickhouse/schema/databases/001_verifications/002_raw_key_verifications_v1.sql:31-33
Timestamp: 2025-04-22T14:40:51.459Z
Learning: The ClickHouse table schemas in the codebase mirror the production environment and cannot be modified directly in PRs without careful migration planning.
📚 Learning: 2025-09-12T13:25:41.814Z
Learnt from: chronark
PR: unkeyed/unkey#3958
File: internal/clickhouse/src/requests.ts:7-8
Timestamp: 2025-09-12T13:25:41.814Z
Learning: In the ClickHouse v2 table migration, the location field was renamed from `colo` to `region` across all tables including `default.api_requests_raw_v2`. The zod insert schemas must be updated accordingly to avoid runtime insert failures.

Applied to files:

  • internal/clickhouse/src/ratelimits.ts
📚 Learning: 2024-10-20T07:05:55.471Z
Learnt from: chronark
PR: unkeyed/unkey#2294
File: apps/api/src/pkg/keys/service.ts:268-271
Timestamp: 2024-10-20T07:05:55.471Z
Learning: In `apps/api/src/pkg/keys/service.ts`, `ratelimitAsync` is a table relation, not a column selection. When querying, ensure that table relations are included appropriately, not as columns.

Applied to files:

  • internal/clickhouse/src/ratelimits.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Test Go API Local / Test
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Packages / Test
  • GitHub Check: Build / Build
🔇 Additional comments (3)
internal/clickhouse/src/ratelimits.ts (3)

226-226: LGTM: last-used reads migrated to v2.

Source table updated to default.ratelimits_last_used_v2 as expected.


289-290: LGTM: colo → region rename reflected in schema.

ratelimitLogs now exposes region: string(), matching v2 metrics.

Please confirm all downstream consumers (Dashboard/SDK) read region and no code still expects colo.


617-617: LGTM: overview queries source v2 and aggregate correctly.

Switched to default.ratelimits_raw_v2; grouping and ordering guardrails look solid.

Also applies to: 626-635, 652-652

@ogzhanolguncu
Copy link
Contributor Author

Lemme test it properly from scratch

Copy link
Collaborator

it works

Copy link
Collaborator

oops wrong thread

@perkinsjr
Copy link
Member

I tested this across the dashboard and everything looks good, all data loaded and matched another branch that didn't use the v2 reads.

@ogzhanolguncu
Copy link
Contributor Author

image Out of context, but I think we should increase density for /logs and /ratelimits charts looks ugly in some cases. Idk maybe I can fix this on FE too. I'll check later.

Copy link
Contributor Author

@ogzhanolguncu ogzhanolguncu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chronark /logs, /apis/, /ratelimits loads correctly. LGTM

@chronark chronark merged commit 79b7637 into main Sep 17, 2025
18 checks passed
@chronark chronark deleted the update-ch-reads branch September 17, 2025 18:08
@chronark
Copy link
Collaborator

@ogzhanolguncu I highly agree

image Out of context, but I think we should increase density for /logs and /ratelimits charts looks ugly in some cases. Idk maybe I can fix this on FE too. I'll check later.

@perkinsjr
Copy link
Member

perkinsjr commented Sep 17, 2025

FYI I have this in a branch that fixes all the destiny. I was waiting for the CH stuff to drop to finish the branch.

https://app.cushion.so/unkey/post/post_GJeqCuQMqJnk00eOi7MFA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants