Skip to content

[Due for payment 2026-10-12] Add account-size telemetry to Sentry (db_size, re-bucketed count tags, transactions_count) #98432

Closed

Description

@melvin-bot

Strategy
The largest accounts are where app performance is compared hardest against competitors, and where slowness hurts retention most. Keeping the app fast for them means our performance work has to target the factors that actually cause slowness for a given group of users, instead of spreading effort evenly.

Background
We use user-level tags in Sentry to split performance data into groups — today we have reports_count, personal_details_count and policies_count (added in #80531). These cover a lot and work well for basic segmentation. Some facts about the data behind them — partly just how the app works, partly what production data shows:

  1. Onyx loads the whole local database into memory on every app start, so startup time grows with database size.
  2. In production span data, nearly all enterprise users report personal_details_count:10000+, and ~95% of all spans carry policies_count:2-10.
  3. Transactions are the most numerous entity in an account — the applause account holds 62.8k transactions vs 13.2k reports.

Problem
When a group of users shows bad p90s in Sentry, we can't tell whether the cause is local data volume or lots of transactions — the size categories we already collect put nearly all users into the same few buckets — so we end up reproducing heavy accounts manually or picking optimization targets by guessing.

Solution
Three independent additions, one per fact above. Each works on its own — we're happy to land just some of them, and we'd like to hear opinions on which ones are worth it.

1. db_size — first ship only the exact db_size_bytes numeric attribute, and once we've collected real data, add a bucketed tag with borders based on the actual size distribution. The value is measured at app start and re-measured whenever the underlying data changes (e.g. report or transaction count changes), through a debounced call so it doesn't fire too often. Each measurement updates the value attached to new spans and is also stored, so on the next app start the last known value is attached right away — every span, including the TTI/startup span, carries it. With this, any span can be filtered by database size, so "slow because the local DB is big" becomes directly checkable. Onyx already exposes Storage.getDatabaseSize() on all platforms: on mobile it reads the SQLite header, so the value is exact and cheap (cost does not grow with DB size); on web a reliable value exists only on Chromium browsers (~92% of our web spans), and everywhere else we report an explicit unavailable.

2. Re-bucket the existing tags in two steps — data first, buckets second

  • a. Add the exact values as numeric span attributes (now) — reports_count_raw, personal_details_count_raw, policies_count_raw, transactions_count_raw. The middleware that already copies tags to child spans (copyTagsToChildSpans) adds them in its existing loop, so it's a few lines of code. Numeric attributes support range filters and aggregations in Sentry (p90(), avg() — this already works for the existing report_action_count attribute), so deep analysis is possible from day one. The existing bucketed tags stay untouched in the meantime.
  • b. Design new buckets for the tags based on the real distributions we collected (after ~1-2 weeks of data) — instead of guessing borders now. We deliberately don't propose the borders yet; that will be a short follow-up once the data is in. Two things we already know for that step: the re-bucketed tags will need new names (e.g. reports_count_v2), because Sentry keeps ~3 months of data and old bucket values would mix with new ones in every query; and bucket labels will need an ordering prefix (e.g. 1_0-100, 2_101-1k), because Sentry sorts tag values alphabetically.

3. transactions_count — a new tag counting transactions. With it, we can compare p90s between users with hundreds vs tens of thousands of transactions and decide whether transaction-heavy accounts need dedicated optimization work. Implementation is simple: same pattern as the existing count tags in TelemetrySynchronizer, one entry in CONST.TELEMETRY.TAGS (child spans get it automatically since #86182). Same caveat as reports_count: this counts the local cache, not the whole account.

Reported in Slack.

Issue OwnerCurrent Issue Owner: @aimane-chnaif
Issue OwnerCurrent Issue Owner: @aimane-chnaif

Activity

  1. melvin-bot commented on Aug 17, 2026

    @melvin-bot
    Author

    @arekm213 Eep! 4 days overdue now. Issues have feelings too...

  2. arekm213 commented on Aug 18, 2026

    @arekm213
    Contributor

    Im working on this issue, i hope to deliver a PR with that tomorrow

  3. melvin-bot commented on Aug 21, 2026

    @melvin-bot
    Author

    @arekm213 Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

  4. 35 remaining items

  5. changed the title [-][Due for payment 2026-09-07] Add account-size telemetry to Sentry (db_size, re-bucketed count tags, transactions_count)[/-] [+][Due for payment 2026-10-12] Add account-size telemetry to Sentry (db_size, re-bucketed count tags, transactions_count)[/+] on Oct 5, 2026
  6. melvin-bot commented on Oct 5, 2026

    @melvin-bot
    Author

    @aimane-chnaif @mallenexpensify

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.2-4 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-10-12. 🎊

    The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]. If no checklist is needed for this issue, you can click: [no checklist button]

  7. aimane-chnaif commented on Oct 6, 2026

    @aimane-chnaif
    Contributor

    Not overdue

  8. melvin-bot commented on Oct 9, 2026

    @melvin-bot
    Author

    @aimane-chnaif Whoops! This issue is 2 days overdue. Let's get this updated quick!

  9. aimane-chnaif commented on Oct 11, 2026

    @aimane-chnaif
    Contributor

    BugZero Checklist:

    • [Contributor] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.

      Link to comment:

    • [Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.

      Link to discussion:

    • [Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.

    • [BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.

      Link to issue: https://github.com/Expensify/Expensify/issues/679893

    Regression Test Proposal

    no need. sentry issue

  10. mallenexpensify commented on Oct 14, 2026

    @mallenexpensify
    Contributor

    @aimane-chnaif is additional payment due here?

  11. aimane-chnaif commented on Oct 14, 2026

    @aimane-chnaif
    Contributor

    yes because it's different PR

  12. mallenexpensify commented on Oct 14, 2026

    @mallenexpensify
    Contributor

    Updated payment summary above

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

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionDailyKSv2Task

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions