
Primary topic Mobile Web
Chrome’s shift to SQLite-backed IndexedDB is expanding beyond Incognito. The stage listed for Chrome 156 covers newly created on-disk storage, while existing LevelDB data stays in place. For mobile sites that save drafts, attachments, and work waiting to sync, the immediate consequence is a transition in which users can have different storage backends on the same browser version.
Google announced Chrome 156.0.8078.47 for Android on October 20, 2026, with availability on Google Play over the following days. The SQLite change deserves a separate check from that browser update. Receiving Chrome 156 does not establish which storage engine a particular site is using.
The application still uses IndexedDB: databases, object stores, indexes, and transactions. Chromium’s announcement of the backend change explicitly preserves the web API. Sites gain no SQL interface, and an existing IndexedDB schema does not need a version bump simply because the browser changes its implementation. The useful work is checking what happens to saved data and transaction timing.
What is actually rolling out?
As of October 22, the ChromeStatus feature record assigns milestone 156 to desktop, Android, and Android WebView, but still labels the implementation status “Proposed.” Those fields describe an intended release milestone without establishing deployment to every installation. The entry supplies no iOS milestone; the Android announcement should not be read as an iPhone storage announcement.
The released 156.0.8078.47 source leaves the on-disk rollout feature disabled by default. Field-trial settings can override that default. In its October 8 validation announcement, Microsoft specifically says Chrome and Edge are experimenting with the change through field trials. Taken together, these sources establish a staged transition; they do not establish a universal activation date or percentage. For a site team, that makes the browser version an insufficient way to classify storage behavior.
This is the second stage of the project. The earlier Chrome 145 release notes covered SQLite for in-memory contexts, including Incognito. The stage listed for Chrome 156 extends the work to new on-disk stores. Migration of existing LevelDB data remains a subsequent stage in the published rollout description. An Incognito test therefore cannot substitute for testing an established user’s on-disk data.
Existing data stays on its current backend
The important boundary is the browser’s storage bucket for the site, rather than the age of the entire browser profile. The backend-selection code in Chrome 156 checks whether a LevelDB store already exists for that bucket. In the new-stores stage, SQLite is selected when it does not.
The practical consequences of that selection rule are:
- A fresh test profile can create SQLite storage when the new-stores rollout stage is enabled.
- An established profile can also create SQLite storage for a site whose bucket has no existing LevelDB store.
- A returning user’s existing LevelDB store stays on LevelDB during this stage. Adding another named IndexedDB database, or another object store inside one, does not by itself change the bucket’s backend.
This distinction matters when reproducing a support report. A developer opening the site in a clean profile may be exercising a different storage path from the person reporting the problem. Preserve an established test profile alongside a clean one. Keep working user data intact: clearing site storage to force a transition can erase the very drafts and queued uploads an offline application exists to protect.
A background import can compete with a draft save
The most visible execution change concerns readwrite transactions. With SQLite, only one can run at a time within a given IndexedDB database, even when the transactions address different object stores. Chromium’s LevelDB implementation could overlap writes when their scopes—the sets of object stores they access—did not intersect. The new implementation still permits eligible readonly transactions to run alongside a write when their scopes do not overlap.
Consider a field-service PWA importing a large catalog while someone saves a job note. If those operations write to separate object stores in the same database, the note’s transaction may have to wait for the import. That is an implication of the scheduling change, not a measured slowdown for every application. The relevant test is the time the user waits for the save confirmation while background work is active.
The IndexedDB scheduling rules already allow browsers to serialize non-overlapping write transactions. Neither implementation creates a general promise about the order in which independent transactions finish. Code with a dependency should express it explicitly, and operations that only read should use readonly.
Keep transactions limited to work that needs to commit together, and measure bulk-write batches against foreground saves. Splitting a database solely to recover parallel writes introduces another tradeoff: as the implementation design explains, separate databases cannot share one atomic IndexedDB transaction. A draft and its upload-queue entry may need that shared commit more than they need additional write concurrency.
Separate databases need coordinated recovery
The architecture changes the possible reach of a storage failure. LevelDB grouped the IndexedDB databases within a storage bucket in one backing store; the SQLite design gives each named database its own SQLite database. The developers’ public technical PSA says unrecoverable corruption or an I/O error may consequently affect one database instead of the whole IndexedDB storage area. This is an expected improvement in isolation, with a qualification for applications that distribute related state across databases.
Suppose one database lists articles available offline and another holds their content. If the list survives a failure affecting the content database, the app can display a download that it can no longer open. Recovery logic should check the relationship between those records, distinguish downloadable content from unsynced user work, and explain incomplete offline availability accurately. Successfully opening one database is not a health check for all of them.
Check the saved attachment itself
Blob handling is another reason for the rewrite. The older implementation kept Blob metadata in LevelDB and the bytes in separate files. The Blob design document explains the difficulty of keeping those stores consistent; the new backend writes new Blob contents into SQLite. The PSA’s authors expect fewer cases in which reading a Blob fails independently of the rest of the database. That remains an expectation, rather than a guarantee that attachments cannot be lost.
For a mobile publishing tool or inspection app, include actual photos, PDFs, or audio in the test data. After the transaction completes, close and reopen the application, retrieve each attachment, and read or decode its contents. A filename in an offline list does not establish that the underlying file can still be used.
Disk use can grow even when writes improve
In their technical PSA, the developers report roughly twice-as-fast writes in benchmarks, while identifying reliability and maintainability as the main goals. That result is not a forecast for a particular phone or workload. A faster individual storage operation can coexist with longer waits between competing transactions.
Storage size also depends on the shape of the data. The compression design describes compressing record values rather than obtaining LevelDB’s block-level compression. Keys and metadata remain uncompressed. The authors expect that some larger values can compress better, while smaller values can fare worse. That potential improvement should not be generalized to stored media files.
Indexes add another cost. The released SQLite implementation duplicates record keys in index entries to speed cursor iteration. Long primary keys and numerous indexes can therefore make a meaningful difference to disk consumption. A test populated with short integer keys and a single index will miss the storage characteristics of a production catalog built around long compound keys.
Use representative key lengths, index counts, record sizes, and attachments when comparing profiles. Include repeated updates and deletions, rather than stopping after the first import. Before redesigning keys or removing indexes, establish which part of the real dataset causes the increase and which queries would become slower without those indexes.
For application-level monitoring, the StorageManager API provides usage and quota estimates through navigator.storage.estimate(). These are useful for tracking storage pressure, but they cover more than one database and should not be treated as an exact SQLite file-size measurement. Exercise the write-failure path as well: the interface must preserve the distinction between data saved locally, data still awaiting a successful local write, and data acknowledged by the server.
Test an established user’s day
Start with two disposable test environments: a profile carrying existing LevelDB data and a clean profile configured for the new-stores stage. Record the browser build and feature configuration with each result. The staged feature parameter documented in Microsoft’s validation request, and present in Chrome 156’s backend-selection code, is:
--enable-features=IdbSqliteOnDiskRollout:stage/UseSqliteForNewStores
Use that browser argument only in a controlled test launch. It selects the new-stores stage; it does not convert an existing healthy LevelDB store. A configured desktop test can make comparisons repeatable, but mobile behavior still needs checking on the Android devices and browser or embedded WebView builds the product supports.
Use the transaction’s complete event, or its equivalent in the IndexedDB library, to establish successful local commit. An individual request’s success event is earlier in the transaction lifecycle; later work can still abort the transaction. Server acknowledgement is a separate application-level milestone.
Run the same user journey in both environments:
- Populate realistic history. Include older records, real index definitions, deleted content, attachments, and pending uploads. Inspect the saved records and indexes in the DevTools Application panel.
- Work offline while the database is busy. Save and edit user content during a background import. Measure foreground save completion and verify that the interface does not declare success prematurely.
- Leave and return. Reopen the application and verify committed records and attachment contents. In the disposable environment, also interrupt work before commit and confirm that recovery does not present an incomplete operation as finished.
- Exercise updates and failures. Run the application’s real schema upgrade against established data, test quota-related write failures, and check how dependent features behave when a required database is unavailable.
- Reconnect and reconcile. Confirm that locally committed work reaches the server, that retried uploads do not create duplicate user actions, and that the interface distinguishes pending work from acknowledged work.
The application also still needs to save while the user is working. Mobiletech’s explanation of the unreliable end of a web page covers why an exit callback cannot carry that responsibility. For valuable local data, persistent storage can reduce exposure to eviction under storage pressure, when granted. It does not turn a browser database into a backup or prevent the user from clearing site data.
A site that passes these checks can keep its IndexedDB interface and let the browser’s staged transition proceed. The decision to change batching, indexes, or recovery behavior should follow an observed problem with the application’s own data. For someone returning to the app after a day offline, the result that matters is straightforward: the draft is still there, the attachment opens, and work waiting to upload has not disappeared.