Skip to content

fix(sentry): sample traces and session replays to stay under quota - #2082

Merged
giladresisi merged 1 commit into
mainfrom
fix/sentry-usage-limits
Sep 16, 2026
Merged

giladresisi merged 1 commit into
mainfrom
fix/sentry-usage-limits

Conversation

@giladresisi

Copy link
Copy Markdown
Collaborator

What kind of change does this PR introduce?

Config change (backend, orchestrator, frontend Sentry init). In initialize.sentry.ts the fixed tracesSampleRate: 1.0 becomes a tracesSampler: requests whose path contains /public/v1/analytics/ are sampled at 1%, all other backend and orchestrator traces (public API, MCP, app API, background jobs) at 20%, and an incoming sampled parent trace keeps its decision. Frontend tracesSampleRate goes from 1.0 to 0.2 (browser and Next.js server), and replaysSessionSampleRate from 1.0 to 0.4. Error events are not sampled, replaysOnErrorSampleRate stays 1.0, and self-hosted setups without a DSN are unaffected.

Why was this change needed?

Every trace and every browser session was sent to Sentry, and at the current rate we are projected to exceed our plan's span and replay quotas this billing period unless usage drops significantly.

Current usage (24h measured on 2026-09-15):

  • Spans: about 77M/day, roughly 2.3B/month. GET /public/v1/analytics/post/:postId alone is about 33M/day (43%), GET /public/v1/posts about 13M/day, MCP about 9M/day, frontend about 1.5M/day.
  • Replays: about 4K sessions/day, roughly 120K/month.

Expected usage after this change (extrapolated from the same day):

  • Spans: about 9M/day, roughly 270M/month (analytics ~0.3M/day, rest of backend ~8.4M/day, frontend ~0.3M/day), about 88% less.
  • Replays: about 1.6K sessions/day, roughly 48K/month plus error sessions.

Sentry recommends lowering the trace sample rate for high-load production backends (https://docs.sentry.io/platforms/javascript/guides/nestjs/configuration/sampling/) and keeping on-error replays at 100% (https://docs.sentry.io/platforms/javascript/session-replay/).

Other information:

Rates were agreed with the team. Possible follow-ups, not in this PR: restoring the Redis cache read for post analytics and not sending spans for cached responses (could allow higher rates), and dropping Prisma internal child spans via ignoreSpans.

QA

  1. Run an Express app with @sentry/nestjs and this tracesSampler, collecting transactions in beforeSendTransaction, and send 3,000 requests each to /public/v1/analytics/post/:id, /public/v1/analytics/:integration, /public/v1/posts, /mcp/:id and /user/self
  2. Expect about 1% of the analytics requests and about 20% of the others to produce transactions (observed: 35, 32, 575, 580 and 556 of 3,000)
  3. Send 200 requests with a sentry-trace header marked sampled; all 200 should produce transactions
  4. Hit a route that throws 50 times; all 50 error events should be sent regardless of trace sampling
  5. Open the frontend with a DSN set and read the Sentry client options in the console: tracesSampleRate 0.2, replaysSessionSampleRate 0.4, replaysOnErrorSampleRate 1
  6. In a session whose sessionStorage.sentryReplaySession has sampled: "buffer", capture an exception; the replay for that session should appear in Sentry with 1 error (verified with the previous 0.25 session rate; the on-error path is unchanged)
  7. After deploy, check the spans/day for the cloud project drops to roughly the expected numbers above

Checklist:

  • I have read the CONTRIBUTING guide.
  • I have signed the Contributor License Agreement (CLA) (ICLA for individuals, CCLA for entities).
  • I confirm I have not used AI to submit this PR or generate code for it.
  • I checked that there were no similar issues or PRs already open for this.
  • This PR fixes just ONE issue
  • I have filled in the QA section above with real steps to verify this change.

🤖 Generated with Claude Code

Backend traces were sent at 100% (about 77M spans/day) and every
browser session was recorded. Sample /public/v1/analytics/* at 1% and
all other backend traces at 20%, frontend traces at 20% and session
replays at 40%. Error events and error-session replays stay at 100%.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@postiz-contribution
postiz-contribution Bot changed the base branch from main to staging September 15, 2026 13:01
@postiz-contribution postiz-contribution Bot added the contribution:approved Approved contributor label Sep 15, 2026
@postiz-contribution
postiz-contribution Bot changed the base branch from staging to main September 15, 2026 13:01
@strix-security

strix-security Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Strix Security Review

No security issues found.

Updated for 73f5e2d.


Reviewed by Strix
Re-run review · Configure security review settings

@postiz-agent

postiz-agent Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues
✅ Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@giladresisi
giladresisi added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit c182d16 Sep 16, 2026
12 checks passed
@giladresisi
giladresisi deleted the fix/sentry-usage-limits branch September 16, 2026 01:23
pull Bot pushed a commit to dubbypanda/postiz-app that referenced this pull request Sep 21, 2026
The MCP server is stateless, so the GET that streamable-HTTP clients send
to open a server-to-client stream is not a supported route: nothing is
ever pushed on it. It is still about a quarter of MCP traffic (roughly
180k-214k of ~750k requests per day), and each one became a Sentry
transaction that stayed open for the life of the held connection
(avg ~5 min, p95 15 min).

Sentry usage is already near its limits, which is why gitroomhq#2082 recently cut
trace sampling from 100% to 20%. There is nothing to learn from traces of
an unsupported route, so tracesSampler now returns 0 for GET on /mcp,
/mcp/:id and the /mcp-oauth* mounts. POST traffic on the same routes, the
legacy /sse/:id transport and the /.well-known discovery routes keep the
existing sample rates.

Pairs with the change that answers these GETs with 405. Deploy this one
after that change has been verified in Sentry, because the verification
reads the GET transactions this commit removes.

Testing:
- Called the real tracesSampler with request contexts shaped like the
  http instrumentation passes them (method and URL via normalizedRequest
  and via span attributes only): GET on the MCP routes returns 0; POST on
  the same routes 0.2; unrelated GETs 0.2; analytics 0.01; legacy /sse
  0.2; /.well-known/.../mcp-oauth discovery 0.2; /mcpfoo 0.2.
- Ran the backend against a Sentry development environment and sent
  140+ GETs and 60+ POSTs to /mcp, /mcp/:id and /mcp-oauth-claude: zero
  GET transactions recorded, POST /mcp and POST /mcp/:id recorded as
  before. Same result on SDK 10.45.0 and 10.56.0.
- Backend type-check passes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant