Skip to content

perf: keep cronjob rescheduling out of the vault's database - #45936

Open
MajorLift wants to merge 9 commits into
mainfrom
feat/cronjob-dates-off-vault-database
Open

perf: keep cronjob rescheduling out of the vault's database#45936
MajorLift wants to merge 9 commits into
mainfrom
feat/cronjob-dates-off-vault-database

Conversation

@MajorLift

@MajorLift MajorLift commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

CHANGELOG entry: Store cronjob event dates through StorageService instead of browser.storage.local, so rescheduling no longer writes to the store that holds the vault.

Summary

CronjobController writes its whole event map to browser.storage.local on every reschedule, under the key temp-cronjob-storage, bypassing PersistenceManager entirely — no lock, no debounce, no backup. A Snap on a PT30S schedule reschedules every thirty seconds. Preinstalled cadences today: bitcoin PT30S, tron PT60S, institutional 5/15 * * * * * plus * * * * *.

None of that belongs in storage.local. getStorageServiceInstanceOptions already puts Snaps data elsewhere, for a reason its own comment states: "Chrome has an issue with its storage.local implementation -- it doesn't like sharing the database with 'large' keys, like Snaps source code." Cronjob rescheduling is the same kind of traffic in the same database.

This PR moves per-event next-run dates onto the StorageService adapter — IndexedDB everywhere except Firefox, where indexedDB can be switched off and browser.storage.local remains the fallback.

  • setEventDate and deleteEventDate write through the same adapter StorageService is built with. The adapter choice now lives in one place, exported from storage-service.ts, rather than being repeated.
  • The event map itself deliberately stays in storage.local. CronjobController.init is #start(); #clear(); #reschedule(); — it only reschedules what is already in state, and manifest cronjobs are registered solely from the endowment:cronjob caveat on snapInstalled / snapEnabled. Losing the map would silently stop every cronjob for an already-installed Snap until it was reinstalled. A date, by contrast, is reconstructible from the event's immutable schedule and scheduledAt.
  • Because the two stores now have different durability, they can drift, so init reconciles them before the controller sees any state. Reconciliation lives in init because it is already async — getInitialState is synchronous and stays that way.
  • Dates orphaned by events that already fired or were cancelled are swept, since nothing removed them before deleteEventDate existed.

Does not close #44802 (flag controller-state writes that bypass PersistenceManager), and is worth reading against it: that issue's acceptance criteria require the cronjob-storage task to have removed CronjobControllerStorageManager and temp-cronjob-storage outright. This PR reduces what that manager writes to storage.local without removing it, so the bypass remains and the criterion is unmet. Adjacent to #45678 (increase persistence debounce to five seconds) and #44009 (flush keyring state persistence), which move the same quantity from the other direction.

Depends on

setEventDate and deleteEventDate are added upstream in MetaMask/snaps#4107 (reduce cronjob write churn by persisting dates separately). Until that lands and releases, CronjobController will not call them, so this change is inert rather than wrong — the manager carries two methods nothing yet invokes, and reconciliation is a no-op against an empty date store.

One recovery tier is left out on purpose. A date lost from both stores is still reconstructible from schedule and scheduledAt via recoverEventDate in that same PR; it is not published yet, so its schedule parsing is not duplicated here. Today such an event is dropped rather than stranded.

What this does not do

The write count is unchanged — the same number of writes happen, against a different store. The vault's own write path is untouched. And on Firefox the adapter falls back to browser.storage.local, so dates stay in the same store there; that is the existing StorageService behaviour rather than something this PR introduces.

Test plan

  • yarn jest app/scripts/lib/CronjobControllerStorageManager.test.ts — 14 passed.
  • Reconciliation is covered in all three drift directions: a date in both stores (the date store wins, because the map's copy is stale by design), a date missing from the date store (falls back to the map), and an orphaned date with no matching event (swept).
  • An event with no usable date in either store is dropped rather than kept, since it could neither fire nor be cleared.
  • setEventDate is asserted to write to the date store and not to browser.storage.local — the whole point of the change.
  • Negative controls: removing the orphan sweep fails the sweep test, and inverting the date precedence fails the precedence test. Both assertions are load-bearing rather than vacuous.

Note

Medium Risk
Changes wallet boot init and cronjob state assembly across two stores; failures are handled best-effort, but reconciliation bugs could drop or mis-schedule Snap cronjobs.

Overview
Moves per-event cronjob next-run dates off browser.storage.local (which also holds the vault) onto the same StorageService adapter used for Snaps data (IndexedDB on Chrome; Firefox keeps the existing fallback). The event map still loads and saves under temp-cronjob-storage in storage.local.

CronjobControllerStorageManager now takes an injectable date store (defaulting to the exported StorageAdapter from storage-service.ts), adds setEventDate / deleteEventDate, and runs init reconciliation: date store wins over stale map dates, falls back to map dates when missing, drops events with no valid date, and best-effort sweeps orphan date keys without failing wallet boot.

Tests cover reconciliation, separate date persistence (no storage.local.set on reschedule writes), and date-store errors during init.

Reviewed by Cursor Bugbot for commit 038f792. Bugbot is set up for automated code reviews on this repo. Configure here.

`browser.storage.local` is one LevelDB instance shared by every key the
extension stores. Compaction re-packs keys into blocks, so a block damaged by
an interrupted compaction fails its checksum for whatever else shares it — a
read of the vault can hit corruption produced while writing something
unrelated. Rescheduling is the most frequent write here and none of it needs
to be in that database.

`IndexedDBEventDateStore` puts the dates in their own IndexedDB database,
deliberately not the one the state backup uses. `init` reconciles the two
stores before the controller sees any state, and sweeps date keys left behind
by events that were cancelled or fired before `deleteEventDate` existed.
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamask-ci metamask-ci Bot added the team-extension-platform Extension Platform team label Sep 1, 2026
@metamask-ci metamask-ci Bot added the INVALID-PR-TEMPLATE PR's body doesn't match template label Sep 1, 2026
Rescheduling is the most frequent write this controller makes, and it was
landing in `browser.storage.local` next to the vault. A next-run date is
reconstructible from the event's `schedule` and `scheduledAt`, so it does not
need that store's durability — `StorageService` already keeps Snaps data out
of `storage.local` for exactly this reason.

The event map itself stays put: `CronjobController.init` only reschedules what
is already in state and never re-derives events from Snap manifests, so losing
the map would silently stop every cronjob.

The two stores can now drift, so `init` reconciles them before the controller
sees any state, and sweeps dates left behind by events that already fired.
@metamask-ci

metamask-ci Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor
Builds ready [7b666f3] [reused from 7609349]
⚡ Performance Benchmarks (Total: 🟢 10 pass · 🟡 8 warn · 🔴 4 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 33547987916 | Baseline logs

Metricschrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 load_new_account(p95) [CI log]🔴 load_new_account(p95) [CI log]
onboardingImportWallet
[Sentry log · main/release]
🔴 srpButtonToSrpForm(p95) [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]

Regressions (🔴 4 failures)

Interaction Benchmarks · Samples: 5 🔴 2
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 [CI log]
🔴 load_new_account
🔴 [CI log]
🔴 load_new_account
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • loadNewAccount/load_new_account: +190%
  • loadNewAccount/total: +190%
  • confirmTx/longTaskTotalDuration: -16%
  • confirmTx/longTaskMaxDuration: +28%
  • confirmTx/tbt: -27%
  • bridgeUserActions/bridge_load_asset_picker: +23%
  • bridgeUserActions/longTaskCount: -44%
  • bridgeUserActions/longTaskTotalDuration: -54%
  • bridgeUserActions/longTaskMaxDuration: -29%
  • bridgeUserActions/tbt: -73%
  • loadNewAccount/load_new_account: +192%
  • loadNewAccount/total: +192%
  • loadNewAccount/fcp: -79%
  • loadNewAccount/lcp: +1105%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/inp: -39%
  • confirmTx/fcp: -86%
  • confirmTx/lcp: +1055%
  • bridgeUserActions/bridge_load_page: +124%
  • bridgeUserActions/bridge_load_asset_picker: +56%
  • bridgeUserActions/bridge_search_token: -11%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/inp: -31%
  • bridgeUserActions/fcp: -59%
  • bridgeUserActions/lcp: +1056%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.8s
Startup Benchmarks · Samples: 100

⚠️ Missing data: firefox/webpack/startupStandardHome, firefox/webpack/startupPowerUserHome

Benchmarkchrome-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/uiStartup: -30%
  • startupStandardHome/load: -28%
  • startupStandardHome/domContentLoaded: -28%
  • startupStandardHome/domInteractive: -21%
  • startupStandardHome/firstPaint: -19%
  • startupStandardHome/backgroundConnect: -22%
  • startupStandardHome/firstReactRender: -99%
  • startupStandardHome/initialActions: -67%
  • startupStandardHome/loadScripts: -29%
  • startupStandardHome/longTaskCount: -33%
  • startupStandardHome/longTaskTotalDuration: -37%
  • startupStandardHome/longTaskMaxDuration: -32%
  • startupStandardHome/tbt: -38%
  • startupStandardHome/inp: -11%
  • startupStandardHome/fcp: -29%
  • startupStandardHome/lcp: -20%
User Journey Benchmarks · Samples: 5 · mock API 🔴 2
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]
🔴 total
🔴 [CI log]
🔴 total
assetDetails
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
🟡 assetClickToPriceChart
importSrpHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/srpButtonToSrpForm: +44%
  • onboardingImportWallet/confirmSrpToPwForm: +47%
  • onboardingImportWallet/pwFormToMetricsScreen: +22%
  • onboardingImportWallet/metricsToWalletReadyScreen: +32%
  • onboardingImportWallet/doneButtonToHomeScreen: -92%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -44%
  • onboardingImportWallet/longTaskCount: -86%
  • onboardingImportWallet/longTaskTotalDuration: -96%
  • onboardingImportWallet/longTaskMaxDuration: -91%
  • onboardingImportWallet/tbt: -99%
  • onboardingImportWallet/total: -79%
  • onboardingNewWallet/srpButtonToPwForm: +31%
  • onboardingNewWallet/skipBackupToMetricsScreen: +31%
  • onboardingNewWallet/agreeButtonToOnboardingSuccess: +20%
  • onboardingNewWallet/doneButtonToAssetList: -16%
  • onboardingNewWallet/longTaskCount: -69%
  • onboardingNewWallet/longTaskTotalDuration: -77%
  • onboardingNewWallet/longTaskMaxDuration: -49%
  • onboardingNewWallet/tbt: -96%
  • onboardingNewWallet/total: -15%
  • solanaAssetDetails/assetClickToPriceChart: +238%
  • solanaAssetDetails/longTaskCount: -100%
  • solanaAssetDetails/longTaskTotalDuration: -100%
  • solanaAssetDetails/longTaskMaxDuration: -100%
  • solanaAssetDetails/tbt: -100%
  • solanaAssetDetails/total: +238%
  • solanaAssetDetails/inp: +11%
  • solanaAssetDetails/fcp: +16%
  • importSrpHome/loginToHomeScreen: -30%
  • importSrpHome/homeAfterImportWithNewWallet: -25%
  • importSrpHome/longTaskCount: -65%
  • importSrpHome/longTaskTotalDuration: -73%
  • importSrpHome/longTaskMaxDuration: -65%
  • importSrpHome/tbt: -80%
  • importSrpHome/total: -25%
  • importSrpHome/inp: -69%
  • importSrpHome/fcp: -17%
  • importSrpHome/cls: +435%
  • sendTransactions/openSendPageFromHome: -20%
  • sendTransactions/reviewTransactionToConfirmationPage: -98%
  • sendTransactions/longTaskCount: -100%
  • sendTransactions/longTaskTotalDuration: -100%
  • sendTransactions/longTaskMaxDuration: -100%
  • sendTransactions/tbt: -100%
  • sendTransactions/total: -92%
  • sendTransactions/inp: -44%
  • sendTransactions/fcp: +13%
  • sendTransactions/lcp: -63%
  • sendTransactions/cls: +171%
  • swap/openSwapPageFromHome: +823%
  • swap/fetchAndDisplaySwapQuotes: +88%
  • swap/longTaskCount: -100%
  • swap/longTaskTotalDuration: -100%
  • swap/longTaskMaxDuration: -100%
  • swap/tbt: -100%
  • swap/total: +102%
  • swap/lcp: -71%
  • swap/cls: -92%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.8s
  • 🟡 solanaAssetDetails/FCP: p75 1.8s
  • 🟡 sendTransactions/FCP: p75 1.9s
  • 🟡 swap/FCP: p75 1.8s
  • 🟡 assetDetails/FCP: p75 1.9s
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/FCP: p75 1.9s
  • 🟡 swap/FCP: p75 1.9s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • dappPageLoad/pageLoadTime: -61%
  • dappPageLoad/firstPaint: -46%
  • dappPageLoad/firstContentfulPaint: -46%
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 1.75 KiB (0.01%)
  • ui: 1.95 KiB (0.01%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 42 Bytes (0%)
  • zip: 936 Bytes (0%)

@MajorLift
MajorLift marked this pull request as ready for review September 9, 2026 13:21
@MajorLift
MajorLift requested review from a team as code owners September 9, 2026 13:21

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0685d6d. Configure here.

Comment thread app/scripts/lib/CronjobControllerStorageManager.ts
@GuillaumeRx

Copy link
Copy Markdown
Contributor

We should probably update the CronjobController to get rid of that temporary fix that was StorageAdapter and use directly the StorageService

@metamask-ci

metamask-ci Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor
Builds ready [0685d6d]
⚡ Performance Benchmarks (Total: 🟢 13 pass · 🟡 10 warn · 🔴 2 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 34356473280 | Baseline logs

Metricschrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 load_new_account(p95) [CI log]🔴 load_new_account(p95) [CI log]

Regressions (🔴 2 failures)

Interaction Benchmarks · Samples: 5 🔴 2
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 [CI log]
🔴 load_new_account
🔴 [CI log]
🔴 load_new_account
confirmTx
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • loadNewAccount/load_new_account: +190%
  • loadNewAccount/total: +190%
  • confirmTx/longTaskTotalDuration: +35%
  • confirmTx/longTaskMaxDuration: +65%
  • confirmTx/tbt: +65%
  • confirmTx/lcp: +18%
  • bridgeUserActions/bridge_load_page: +52%
  • bridgeUserActions/bridge_load_asset_picker: +31%
  • bridgeUserActions/longTaskCount: +67%
  • bridgeUserActions/longTaskTotalDuration: +46%
  • bridgeUserActions/longTaskMaxDuration: -14%
  • bridgeUserActions/inp: +15%
  • loadNewAccount/load_new_account: +192%
  • loadNewAccount/total: +192%
  • loadNewAccount/fcp: +13%
  • loadNewAccount/lcp: +1154%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/inp: -24%
  • confirmTx/fcp: -58%
  • confirmTx/lcp: +1243%
  • bridgeUserActions/bridge_load_page: +301%
  • bridgeUserActions/bridge_load_asset_picker: +172%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +44%
  • bridgeUserActions/inp: +38%
  • bridgeUserActions/fcp: -45%
  • bridgeUserActions/lcp: +1176%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.8s
  • 🟡 confirmTx/FCP: p75 1.8s
  • 🟡 bridgeUserActions/FCP: p75 1.8s
  • 🟡 loadNewAccount/FCP: p75 2.0s
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/firstReactRender: -99%
  • startupStandardHome/initialActions: -33%
  • startupStandardHome/domInteractive: -29%
  • startupStandardHome/firstReactRender: -98%
  • startupStandardHome/initialActions: -50%
  • startupStandardHome/setupStore: +24%
  • startupStandardHome/fcp: -24%
  • startupPowerUserHome/load: +16%
  • startupPowerUserHome/domContentLoaded: +16%
  • startupPowerUserHome/firstReactRender: -99%
  • startupPowerUserHome/initialActions: -44%
  • startupPowerUserHome/loadScripts: +15%
  • startupPowerUserHome/setupStore: -76%
  • startupPowerUserHome/numNetworkReqs: -48%
  • startupPowerUserHome/inp: +27%
  • startupPowerUserHome/lcp: +14%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/INP: p75 240ms
  • 🟡 startupPowerUserHome/LCP: p75 3.3s
User Journey Benchmarks · Samples: 5 · mock API
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 total
assetDetails
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/srpButtonToSrpForm: +38%
  • onboardingImportWallet/confirmSrpToPwForm: +52%
  • onboardingImportWallet/pwFormToMetricsScreen: +23%
  • onboardingImportWallet/metricsToWalletReadyScreen: +23%
  • onboardingImportWallet/doneButtonToHomeScreen: -92%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -94%
  • onboardingImportWallet/longTaskCount: -100%
  • onboardingImportWallet/longTaskTotalDuration: -100%
  • onboardingImportWallet/longTaskMaxDuration: -100%
  • onboardingImportWallet/tbt: -100%
  • onboardingImportWallet/total: -91%
  • onboardingNewWallet/srpButtonToPwForm: +23%
  • onboardingNewWallet/createPwToRecoveryScreen: +10%
  • onboardingNewWallet/skipBackupToMetricsScreen: +20%
  • onboardingNewWallet/agreeButtonToOnboardingSuccess: +20%
  • onboardingNewWallet/doneButtonToAssetList: -81%
  • onboardingNewWallet/longTaskCount: -69%
  • onboardingNewWallet/longTaskTotalDuration: -79%
  • onboardingNewWallet/longTaskMaxDuration: -52%
  • onboardingNewWallet/tbt: -100%
  • onboardingNewWallet/total: -77%
  • solanaAssetDetails/assetClickToPriceChart: +284%
  • solanaAssetDetails/longTaskCount: -100%
  • solanaAssetDetails/longTaskTotalDuration: -100%
  • solanaAssetDetails/longTaskMaxDuration: -100%
  • solanaAssetDetails/tbt: -100%
  • solanaAssetDetails/total: +284%
  • solanaAssetDetails/inp: +19%
  • solanaAssetDetails/fcp: +17%
  • solanaAssetDetails/lcp: +15%
  • importSrpHome/loginToHomeScreen: -27%
  • importSrpHome/longTaskCount: -30%
  • importSrpHome/longTaskTotalDuration: -47%
  • importSrpHome/longTaskMaxDuration: -61%
  • importSrpHome/tbt: -63%
  • importSrpHome/inp: -61%
  • importSrpHome/cls: +474%
  • sendTransactions/openSendPageFromHome: +31%
  • sendTransactions/selectTokenToSendFormLoaded: -32%
  • sendTransactions/reviewTransactionToConfirmationPage: -98%
  • sendTransactions/longTaskCount: -100%
  • sendTransactions/longTaskTotalDuration: -100%
  • sendTransactions/longTaskMaxDuration: -100%
  • sendTransactions/tbt: -100%
  • sendTransactions/total: -95%
  • sendTransactions/inp: -52%
  • sendTransactions/fcp: -15%
  • sendTransactions/lcp: -63%
  • sendTransactions/cls: +171%
  • swap/openSwapPageFromHome: +646%
  • swap/fetchAndDisplaySwapQuotes: +84%
  • swap/longTaskCount: -100%
  • swap/longTaskTotalDuration: -100%
  • swap/longTaskMaxDuration: -100%
  • swap/tbt: -100%
  • swap/total: +96%
  • swap/inp: -27%
  • swap/fcp: -23%
  • swap/lcp: -76%
  • swap/cls: -92%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.8s
  • 🟡 solanaAssetDetails/FCP: p75 1.8s
  • 🟡 importSrpHome/FCP: p75 1.8s
  • 🟡 assetDetails/FCP: p75 2.0s
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/FCP: p75 1.9s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • dappPageLoad/pageLoadTime: -56%
  • dappPageLoad/firstPaint: -41%
  • dappPageLoad/firstContentfulPaint: -41%
Bundle size diffs
  • background: 900 Bytes (0.01%)
  • ui: 60 Bytes (0%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 0 Bytes (0%)
  • zip: 358 Bytes (0%)

`isJsonRecord` reimplemented a predicate `@metamask/utils` already exports, in
a file that imports from that package on the line above, and diverged from the
`isObject` + `hasProperty` pattern `persistence-manager` uses for the same job.
The wrapper stays only to narrow to `Record<string, Json>` rather than
`RuntimeObject`, since callers here have already been through `isValidJson`.
`isJsonRecord` had already been reduced to `return isObject(value)`, kept on
the claim that it narrowed usefully to `Record<string, Json>`. It does not:
`tsc` reports no errors in this file with both the alias and the guard gone,
using `isObject` directly.
@metamask-ci

metamask-ci Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor
Builds ready [fc821eb]
⚡ Performance Benchmarks (Total: 🟢 13 pass · 🟡 8 warn · 🔴 4 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 34362968072 | Baseline logs

Metricschrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 load_new_account(p95) [CI log]🔴 load_new_account(p95) [CI log]
onboardingNewWallet
[Sentry log · main/release]
🔴 createPwToRecoveryScreen(p95) [CI log]🔴 [CI log]

Regressions (🔴 4 failures)

Interaction Benchmarks · Samples: 5 🔴 2
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 [CI log]
🔴 load_new_account
🔴 [CI log]
🔴 load_new_account
confirmTx
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • loadNewAccount/load_new_account: +191%
  • loadNewAccount/total: +191%
  • confirmTx/longTaskTotalDuration: +44%
  • confirmTx/longTaskMaxDuration: +81%
  • confirmTx/tbt: +77%
  • confirmTx/fcp: +13%
  • bridgeUserActions/bridge_load_page: +62%
  • bridgeUserActions/bridge_load_asset_picker: +32%
  • bridgeUserActions/longTaskCount: +67%
  • bridgeUserActions/longTaskTotalDuration: +88%
  • bridgeUserActions/longTaskMaxDuration: +28%
  • bridgeUserActions/tbt: +136%
  • bridgeUserActions/total: +15%
  • loadNewAccount/load_new_account: +190%
  • loadNewAccount/total: +190%
  • loadNewAccount/fcp: -44%
  • loadNewAccount/lcp: +1169%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/inp: -24%
  • confirmTx/fcp: -45%
  • confirmTx/lcp: +1164%
  • bridgeUserActions/bridge_load_page: +337%
  • bridgeUserActions/bridge_load_asset_picker: +118%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +37%
  • bridgeUserActions/inp: +23%
  • bridgeUserActions/fcp: -61%
  • bridgeUserActions/lcp: +1240%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.9s
  • 🟡 confirmTx/FCP: p75 1.9s
  • 🟡 bridgeUserActions/FCP: p75 1.8s
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/firstReactRender: -99%
  • startupStandardHome/initialActions: -33%
  • startupStandardHome/setupStore: +29%
  • startupStandardHome/domInteractive: -32%
  • startupStandardHome/firstReactRender: -98%
  • startupStandardHome/initialActions: -50%
  • startupStandardHome/setupStore: +18%
  • startupStandardHome/fcp: -29%
  • startupPowerUserHome/domInteractive: -51%
  • startupPowerUserHome/backgroundConnect: -16%
  • startupPowerUserHome/firstReactRender: -99%
  • startupPowerUserHome/initialActions: -44%
  • startupPowerUserHome/setupStore: -75%
  • startupPowerUserHome/numNetworkReqs: -48%
  • startupPowerUserHome/inp: +19%
  • startupPowerUserHome/fcp: -51%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/INP: p75 224ms
  • 🟡 startupPowerUserHome/LCP: p75 2.9s
User Journey Benchmarks · Samples: 5 · mock API 🔴 2
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🔴 [CI log]
🔴 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/confirmSrpToPwForm: +10%
  • onboardingImportWallet/pwFormToMetricsScreen: -11%
  • onboardingImportWallet/metricsToWalletReadyScreen: +10%
  • onboardingImportWallet/doneButtonToHomeScreen: -87%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -94%
  • onboardingImportWallet/longTaskCount: -100%
  • onboardingImportWallet/longTaskTotalDuration: -100%
  • onboardingImportWallet/longTaskMaxDuration: -100%
  • onboardingImportWallet/tbt: -100%
  • onboardingImportWallet/total: -88%
  • onboardingNewWallet/agreeButtonToOnboardingSuccess: -15%
  • onboardingNewWallet/doneButtonToAssetList: -15%
  • onboardingNewWallet/longTaskCount: -100%
  • onboardingNewWallet/longTaskTotalDuration: -100%
  • onboardingNewWallet/longTaskMaxDuration: -100%
  • onboardingNewWallet/tbt: -100%
  • onboardingNewWallet/total: -15%
  • solanaAssetDetails/assetClickToPriceChart: +228%
  • solanaAssetDetails/longTaskCount: -100%
  • solanaAssetDetails/longTaskTotalDuration: -100%
  • solanaAssetDetails/longTaskMaxDuration: -100%
  • solanaAssetDetails/tbt: -100%
  • solanaAssetDetails/total: +228%
  • solanaAssetDetails/fcp: +13%
  • importSrpHome/loginToHomeScreen: -32%
  • importSrpHome/homeAfterImportWithNewWallet: -22%
  • importSrpHome/longTaskCount: -58%
  • importSrpHome/longTaskTotalDuration: -67%
  • importSrpHome/longTaskMaxDuration: -65%
  • importSrpHome/tbt: -75%
  • importSrpHome/total: -21%
  • importSrpHome/inp: -66%
  • importSrpHome/cls: +436%
  • sendTransactions/openSendPageFromHome: +72%
  • sendTransactions/reviewTransactionToConfirmationPage: -98%
  • sendTransactions/longTaskCount: -100%
  • sendTransactions/longTaskTotalDuration: -100%
  • sendTransactions/longTaskMaxDuration: -100%
  • sendTransactions/tbt: -100%
  • sendTransactions/total: -94%
  • sendTransactions/inp: -33%
  • sendTransactions/lcp: -54%
  • sendTransactions/cls: +171%
  • swap/openSwapPageFromHome: +286%
  • swap/fetchAndDisplaySwapQuotes: +86%
  • swap/longTaskCount: -100%
  • swap/longTaskTotalDuration: -100%
  • swap/longTaskMaxDuration: -100%
  • swap/tbt: -100%
  • swap/total: +90%
  • swap/lcp: -70%
  • swap/cls: -92%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.8s
  • 🟡 solanaAssetDetails/FCP: p75 1.8s
  • 🟡 importSrpHome/FCP: p75 1.8s
  • 🟡 sendTransactions/FCP: p75 1.9s
  • 🟡 swap/FCP: p75 2.0s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • dappPageLoad/pageLoadTime: -57%
  • dappPageLoad/firstPaint: -46%
  • dappPageLoad/firstContentfulPaint: -46%
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 1.11 KiB (0.01%)
  • ui: 1.15 KiB (0.01%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 14 Bytes (0%)
  • zip: 809 Bytes (0%)

`getAllKeys` and `removeItem` reject on adapter failure, unlike `getItem`
which reports one as a miss. The orphan sweep awaited both from `init`, on the
boot path, so an IndexedDB open or quota error stopped the wallet starting
while the durable event map was still usable.

The sweep is best-effort cleanup on a store whose contents are reconstructible
from `schedule` and `scheduledAt`, so it now logs and continues.
@sonarqubecloud

sonarqubecloud Bot commented Sep 9, 2026

Copy link
Copy Markdown

@metamask-ci

metamask-ci Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor
Builds ready [038f792]
⚡ Performance Benchmarks (Total: 🟢 11 pass · 🟡 11 warn · 🔴 3 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 34366808217 | Baseline logs

Metricschrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 load_new_account(p95) [CI log]🔴 load_new_account(p95) [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]

Regressions (🔴 3 failures)

Interaction Benchmarks · Samples: 5 🔴 2
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 [CI log]
🔴 load_new_account
🔴 [CI log]
🔴 load_new_account
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • loadNewAccount/load_new_account: +191%
  • loadNewAccount/total: +191%
  • loadNewAccount/lcp: +14%
  • confirmTx/longTaskTotalDuration: +30%
  • confirmTx/longTaskMaxDuration: +53%
  • confirmTx/tbt: +63%
  • bridgeUserActions/bridge_load_page: +46%
  • bridgeUserActions/bridge_load_asset_picker: +57%
  • bridgeUserActions/longTaskCount: +67%
  • bridgeUserActions/longTaskTotalDuration: +81%
  • bridgeUserActions/longTaskMaxDuration: +21%
  • bridgeUserActions/tbt: +116%
  • bridgeUserActions/inp: +15%
  • loadNewAccount/load_new_account: +194%
  • loadNewAccount/total: +194%
  • loadNewAccount/inp: +36%
  • loadNewAccount/fcp: -71%
  • loadNewAccount/lcp: +1166%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/inp: -32%
  • confirmTx/lcp: +1028%
  • bridgeUserActions/bridge_load_page: +144%
  • bridgeUserActions/bridge_load_asset_picker: +260%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +37%
  • bridgeUserActions/fcp: -64%
  • bridgeUserActions/lcp: +1010%
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 loadScripts
startupPowerUserHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/firstPaint: +12%
  • startupStandardHome/firstReactRender: -99%
  • startupStandardHome/initialActions: -33%
  • startupStandardHome/setupStore: +36%
  • startupStandardHome/firstReactRender: -98%
  • startupStandardHome/initialActions: -50%
  • startupStandardHome/setupStore: +24%
  • startupPowerUserHome/domInteractive: -27%
  • startupPowerUserHome/backgroundConnect: -18%
  • startupPowerUserHome/firstReactRender: -99%
  • startupPowerUserHome/initialActions: -44%
  • startupPowerUserHome/setupStore: -78%
  • startupPowerUserHome/numNetworkReqs: -48%
  • startupPowerUserHome/inp: +23%
  • startupPowerUserHome/fcp: -26%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/INP: p75 232ms
  • 🟡 startupPowerUserHome/LCP: p75 2.9s
User Journey Benchmarks · Samples: 5 · mock API 🔴 1
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟡 [CI log]
🟡 total
🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]
🔴 total
assetDetails
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
swap
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
🟡 total

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/doneButtonToHomeScreen: -80%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -94%
  • onboardingImportWallet/longTaskCount: -100%
  • onboardingImportWallet/longTaskTotalDuration: -100%
  • onboardingImportWallet/longTaskMaxDuration: -100%
  • onboardingImportWallet/tbt: -100%
  • onboardingImportWallet/total: -83%
  • onboardingNewWallet/srpButtonToPwForm: +21%
  • onboardingNewWallet/createPwToRecoveryScreen: +11%
  • onboardingNewWallet/skipBackupToMetricsScreen: +42%
  • onboardingNewWallet/agreeButtonToOnboardingSuccess: +20%
  • onboardingNewWallet/doneButtonToAssetList: -81%
  • onboardingNewWallet/longTaskCount: -100%
  • onboardingNewWallet/longTaskTotalDuration: -100%
  • onboardingNewWallet/longTaskMaxDuration: -100%
  • onboardingNewWallet/tbt: -100%
  • onboardingNewWallet/total: -77%
  • solanaAssetDetails/assetClickToPriceChart: +255%
  • solanaAssetDetails/longTaskCount: -100%
  • solanaAssetDetails/longTaskTotalDuration: -100%
  • solanaAssetDetails/longTaskMaxDuration: -100%
  • solanaAssetDetails/tbt: -100%
  • solanaAssetDetails/total: +255%
  • solanaAssetDetails/inp: +19%
  • solanaAssetDetails/fcp: +20%
  • importSrpHome/loginToHomeScreen: -22%
  • importSrpHome/longTaskCount: -30%
  • importSrpHome/longTaskTotalDuration: -52%
  • importSrpHome/longTaskMaxDuration: -62%
  • importSrpHome/tbt: -66%
  • importSrpHome/inp: -48%
  • importSrpHome/cls: +477%
  • sendTransactions/openSendPageFromHome: +41%
  • sendTransactions/reviewTransactionToConfirmationPage: -98%
  • sendTransactions/longTaskCount: -100%
  • sendTransactions/longTaskTotalDuration: -100%
  • sendTransactions/longTaskMaxDuration: -100%
  • sendTransactions/tbt: -100%
  • sendTransactions/total: -94%
  • sendTransactions/inp: -44%
  • sendTransactions/fcp: +13%
  • sendTransactions/lcp: -61%
  • sendTransactions/cls: +171%
  • swap/openSwapPageFromHome: +266%
  • swap/fetchAndDisplaySwapQuotes: +85%
  • swap/longTaskCount: +33%
  • swap/longTaskTotalDuration: -12%
  • swap/tbt: -100%
  • swap/total: +89%
  • swap/lcp: -71%
  • swap/cls: -92%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.9s
  • 🟡 solanaAssetDetails/FCP: p75 1.9s
  • 🟡 importSrpHome/FCP: p75 1.8s
  • 🟡 sendTransactions/FCP: p75 1.9s
  • 🟡 swap/FCP: p75 1.8s
  • 🟡 importSrpHome/FCP: p75 1.9s
  • 🟡 sendTransactions/FCP: p75 1.9s
  • 🟡 swap/FCP: p75 1.9s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • dappPageLoad/pageLoadTime: -57%
  • dappPageLoad/firstPaint: -46%
  • dappPageLoad/firstContentfulPaint: -46%
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 1.16 KiB (0.01%)
  • ui: 1.12 KiB (0.01%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 14 Bytes (0%)
  • zip: 790 Bytes (0%)

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

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template risk:high size-M team-extension-platform Extension Platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flag controller-state writes that bypass PersistenceManager

2 participants