TL;DR: On an iPhone 14 Pro running iOS 26.2.1, the Safari/WebKit page process is killed every ~30–90 s (silent full page reload, occasionally Safari's "This webpage was reloaded because it repeatedly caused problems") in any web app session where the PowerSync WASM module has been loaded — even after close()-ing the database. Sessions where the module is never imported are completely stable. Reproduced on both @powersync/web 1.38.3 (wa-sqlite 1.7.0) and 2.2.0 (@journeyapps/wa-sqlite 2.0.3, default settings). No issues on Android Chrome or desktop browsers with the same app and account.
Environment
Device: iPhone 14 Pro, iOS 26.2.1 (first noticed after updating to iOS 26.2.x; same app was fine before)
Browser: Safari — both as an installed PWA (standalone) and in a regular Safari tab
SDK: reproduced on @powersync/web@1.38.3 + @journeyapps/wa-sqlite@1.7.0, and on @powersync/web@2.2.0 + @journeyapps/wa-sqlite@2.0.3
Bundler: Vite 5, worker: { format: 'es' }, optimizeDeps.exclude: ['@journeyapps/wa-sqlite', '@powersync/web'], SDK loaded via dynamic import()
VFS: default (IndexedDB-based); no OPFS, no encryption
Backend: PowerSync Cloud + Supabase (JWT), small dataset (< 1 MB, a dozen synced tables)
Not affected: Android Chrome, desktop Chrome/Edge — same app, same account, zero incidents
Symptom
With a logged-in session (SDK active), the page dies without any lifecycle events (pagehide/visibilitychange never fire) roughly every 30–90 s while the app is in the foreground and being used normally. The page then reloads from scratch. Sometimes Safari shows "This webpage was reloaded because it repeatedly caused problems." Nothing appears in the console before death — it looks like the OS/WebKit killing the web content process, not a JS error.
How we measured (watchdog)
We instrumented the app with a heartbeat watchdog: a localStorage heartbeat every 5 s carrying route, session state, whether the PowerSync DB instance was open, and threading mode; pagehide/visibilitychange write a "goodbye" marker. On boot, a heartbeat without a goodbye = the page died without permission. (It has multi-tab false-positive protection and is biased to undercount.)
Sample from a run on 2.2.0 (fresh origin, default settings, single-thread mode on):
2026-08-24T15:22:58Z · /mas · lived 81s · session · DB closed
2026-08-24T15:29:17Z · /habitos · lived 377s · session · DB open
2026-08-24T15:30:23Z · /habitos · lived 60s · session · DB open
2026-08-24T15:31:21Z · / · lived 55s · session · DB open
2026-08-24T15:32:31Z · / · lived 65s · session · DB open
2026-08-24T15:33:35Z · / · lived 59s · session · DB open
2026-08-24T15:34:20Z · /mas · lived 40s · session · DB open
2026-08-24T15:35:17Z · /mas · lived 55s · session · DB closed
Earlier runs on 1.38.3 show the same shape (cycles of ~30–65 s; 60+ events collected across sessions).
What the evidence isolates
A/B/A on session: logged in → crash every 30–60 s on any route; logged out (SDK never loads) → zero crashes over long sessions; log back in → crashes return. Repeated cleanly.
Not the open DB handle: we added lifecycle management that disconnect()s and close()s the database when no data screen needs it. Crashes continue, including events recorded with the DB closed (see log). Once the WASM module has been loaded in the page's lifetime, the page is doomed.
Module-level A/B (repeated 3×): if the screens/hooks that would trigger the SDK's dynamic import() are disabled (so the WASM module is never fetched/compiled), the same logged-in session is completely stable. Re-enabling a single such screen brings the crash loop back within a minute.
Single-threaded mode doesn't fix it: useWebWorker: false + enableMultiTabs: false lengthens the cycle (~30 s → ~45–65 s) but the kills continue. (Also relevant: we checked our shipped glue for SharedArrayBuffer/new Worker usage — the build doesn't use shared WASM memory, so emscripten-core/emscripten#25905, the known iOS 26.2 shared-memory regression, doesn't seem to apply.)
Upgrade didn't change it: 1.38.3 → 2.2.0 on a fresh origin (default HTTP streaming, default open options) reproduces the identical pattern.
Our working hypothesis
The periodicity and the "module loaded ⇒ death, even when idle/closed" signature smell like WebKit's memory-pressure killer reacting to something that recurs as long as the compiled module is alive — possibly re-JIT/recompilation spikes of the large wasm module, in the spirit of what's described in rhashimoto/wa-sqlite#94 (Apple-silicon/iOS JIT memory spikes). But we have no way to confirm from JS, since the process dies without a trace.
Questions
Are there other reports of iOS 26.2.x killing pages with @powersync/web loaded? Anything known on your side?
Is there a recommended configuration to reduce WASM/JIT memory footprint on iOS (different VFS, interpreter-ish build, smaller module, prepared-statement cache off, etc.) worth A/B-testing?
Any way you'd suggest to get more diagnostic signal out of WebKit here (we can run any instrumented build on the affected device and report back — we have the watchdog + a willing tester)?
Happy to provide more data, run experiments on the device, or test branches. Thanks!
TL;DR: On an iPhone 14 Pro running iOS 26.2.1, the Safari/WebKit page process is killed every ~30–90 s (silent full page reload, occasionally Safari's "This webpage was reloaded because it repeatedly caused problems") in any web app session where the PowerSync WASM module has been loaded — even after close()-ing the database. Sessions where the module is never imported are completely stable. Reproduced on both @powersync/web 1.38.3 (wa-sqlite 1.7.0) and 2.2.0 (@journeyapps/wa-sqlite 2.0.3, default settings). No issues on Android Chrome or desktop browsers with the same app and account.
Environment
Device: iPhone 14 Pro, iOS 26.2.1 (first noticed after updating to iOS 26.2.x; same app was fine before)
Browser: Safari — both as an installed PWA (standalone) and in a regular Safari tab
SDK: reproduced on @powersync/web@1.38.3 + @journeyapps/wa-sqlite@1.7.0, and on @powersync/web@2.2.0 + @journeyapps/wa-sqlite@2.0.3
Bundler: Vite 5, worker: { format: 'es' }, optimizeDeps.exclude: ['@journeyapps/wa-sqlite', '@powersync/web'], SDK loaded via dynamic import()
VFS: default (IndexedDB-based); no OPFS, no encryption
Backend: PowerSync Cloud + Supabase (JWT), small dataset (< 1 MB, a dozen synced tables)
Not affected: Android Chrome, desktop Chrome/Edge — same app, same account, zero incidents
Symptom
With a logged-in session (SDK active), the page dies without any lifecycle events (pagehide/visibilitychange never fire) roughly every 30–90 s while the app is in the foreground and being used normally. The page then reloads from scratch. Sometimes Safari shows "This webpage was reloaded because it repeatedly caused problems." Nothing appears in the console before death — it looks like the OS/WebKit killing the web content process, not a JS error.
How we measured (watchdog)
We instrumented the app with a heartbeat watchdog: a localStorage heartbeat every 5 s carrying route, session state, whether the PowerSync DB instance was open, and threading mode; pagehide/visibilitychange write a "goodbye" marker. On boot, a heartbeat without a goodbye = the page died without permission. (It has multi-tab false-positive protection and is biased to undercount.)
Sample from a run on 2.2.0 (fresh origin, default settings, single-thread mode on):
2026-08-24T15:22:58Z · /mas · lived 81s · session · DB closed
2026-08-24T15:29:17Z · /habitos · lived 377s · session · DB open
2026-08-24T15:30:23Z · /habitos · lived 60s · session · DB open
2026-08-24T15:31:21Z · / · lived 55s · session · DB open
2026-08-24T15:32:31Z · / · lived 65s · session · DB open
2026-08-24T15:33:35Z · / · lived 59s · session · DB open
2026-08-24T15:34:20Z · /mas · lived 40s · session · DB open
2026-08-24T15:35:17Z · /mas · lived 55s · session · DB closed
Earlier runs on 1.38.3 show the same shape (cycles of ~30–65 s; 60+ events collected across sessions).
What the evidence isolates
A/B/A on session: logged in → crash every 30–60 s on any route; logged out (SDK never loads) → zero crashes over long sessions; log back in → crashes return. Repeated cleanly.
Not the open DB handle: we added lifecycle management that disconnect()s and close()s the database when no data screen needs it. Crashes continue, including events recorded with the DB closed (see log). Once the WASM module has been loaded in the page's lifetime, the page is doomed.
Module-level A/B (repeated 3×): if the screens/hooks that would trigger the SDK's dynamic import() are disabled (so the WASM module is never fetched/compiled), the same logged-in session is completely stable. Re-enabling a single such screen brings the crash loop back within a minute.
Single-threaded mode doesn't fix it: useWebWorker: false + enableMultiTabs: false lengthens the cycle (~30 s → ~45–65 s) but the kills continue. (Also relevant: we checked our shipped glue for SharedArrayBuffer/new Worker usage — the build doesn't use shared WASM memory, so emscripten-core/emscripten#25905, the known iOS 26.2 shared-memory regression, doesn't seem to apply.)
Upgrade didn't change it: 1.38.3 → 2.2.0 on a fresh origin (default HTTP streaming, default open options) reproduces the identical pattern.
Our working hypothesis
The periodicity and the "module loaded ⇒ death, even when idle/closed" signature smell like WebKit's memory-pressure killer reacting to something that recurs as long as the compiled module is alive — possibly re-JIT/recompilation spikes of the large wasm module, in the spirit of what's described in rhashimoto/wa-sqlite#94 (Apple-silicon/iOS JIT memory spikes). But we have no way to confirm from JS, since the process dies without a trace.
Questions
Are there other reports of iOS 26.2.x killing pages with @powersync/web loaded? Anything known on your side?
Is there a recommended configuration to reduce WASM/JIT memory footprint on iOS (different VFS, interpreter-ish build, smaller module, prepared-statement cache off, etc.) worth A/B-testing?
Any way you'd suggest to get more diagnostic signal out of WebKit here (we can run any instrumented build on the affected device and report back — we have the watchdog + a willing tester)?
Happy to provide more data, run experiments on the device, or test branches. Thanks!