rei.r.joshua • July 16, 2026

I recently went down a rabbit hole around IndexedDB.

IndexedDB is not new. It has existed in browsers for well over a decade and gives web applications a structured database capable of persisting meaningful amounts of data directly on the user’s device.

What surprised me was not that it existed.

What surprised me was how rarely I had seen it seriously considered as part of normal web architecture.

I have worked in web development for roughly 14 years, much of that time building commerce and enterprise applications. Browser storage is usually treated as a shallow set of options:

  • Cookies when the server needs the value
  • sessionStorage for temporary state
  • localStorage for a few persistent preferences
  • A server database for anything important

That mental model skips an entire architectural layer.

Modern browsers can persist structured application data, process large files away from the UI thread, and run compiled code through WebAssembly.

Once those capabilities are considered together, a more interesting question emerges:

Does the application actually need to take custody of the user’s data?

That question led me toward what I have started calling Local Data Custody.

Where this idea fits

The idea that a web application does not need to store its users’ data on the developer’s server is not new.

The unhosted web movement described applications where the developer hosted the application but not necessarily the user’s data. That data could remain in the browser or live in storage selected by the user.

Local-first software later developed a broader model in which the local copy is primary, while servers may still provide synchronization, collaboration, backup, and access across devices.

The idea has also been discussed as the local-only web, including the unresolved question of how a browser could prove that locally held data cannot be transmitted by the application.

Existing tools already demonstrate parts of the pattern. CyberChef, for example, performs its processing inside the browser and does not need to send normal input data to a server.

So I am not claiming to have discovered browser-local processing or invented a new category of software. That would be a fairly ambitious conclusion to reach after reading about IndexedDB for an afternoon.

My take is narrower:

Custody of a defined class of user data should be treated as an explicit architectural decision.

Offline-first asks whether an application continues working without a network connection.

Local-first asks whether the local copy remains primary, often while retaining cloud synchronization.

Client-side processing tells us where a particular operation runs.

The question I am interested in is:

Does the application operator ever need to receive or possess this data?

That is the lens I mean when I use the term Local Data Custody. More precisely, I am describing browser-local data custody.

What I mean by Local Data Custody

Local Data Custody is a web application approach where a defined class of protected user data is processed and persisted on the user’s device rather than sent to systems operated by the application provider.

I am using custody here in an architectural sense: whether the protected data enters infrastructure operated by the provider. I am not using it as a legal conclusion about ownership, regulatory control, or responsibility.

The server still delivers the application:

  • HTML
  • JavaScript
  • CSS
  • Images
  • Web Workers
  • WebAssembly modules
  • Public content and configuration

The difference is where the user’s working data lives.

The server delivers the capability.

The browser owns the workspace.

This does not mean the website receives no network traffic. The hosting platform still receives requests for application assets and may observe ordinary request information such as IP addresses, timestamps, requested URLs, and user-agent details.

The custody boundary applies to a specific protected data class.

For a Salesforce log analyzer, that class can include:

  • Uploaded or pasted log contents
  • Parsed execution events
  • Salesforce record IDs
  • Names and email addresses
  • Tokens or authorization details
  • Saved analysis history

The claim is not:

This website receives nothing.

The claim is:

The current application does not send your logs or analysis results to the application operator.

That is narrower, but it is also specific enough to design around, test, and explain honestly.

Applying it to the Asyncronaut Log Analyzer

The Asyncronaut Salesforce Log Analyzer now uses this architecture in production.

A common server-centric implementation would look something like this:

Select a log → upload it to an API → process it on a server → store or serialize the result → return the result → display it in the browser

The server owns the workspace.

Five-step server-centric web application pattern in which a user selects a log, uploads it to provider infrastructure for storage and processing, receives the results, and views them in the browser
A common server-centric flow places both protected data and the working environment inside provider-operated infrastructure.

The local-custody version is different:

Select or paste a log → process it in the browser → display the result → optionally save the workspace in the browser

The browser owns the workspace.

Four-step Local Data Custody pattern in which a log is processed by a Web Worker and Rust WebAssembly inside the browser, optionally persisted in IndexedDB, and displayed without sending protected data to the operator
The local-custody flow keeps processing, results, and optional persistence inside the user’s browser.

When someone selects or pastes a log into the Asyncronaut analyzer, the source remains inside the browser. It is transferred to a dedicated Web Worker, where a Rust parser compiled to WebAssembly performs the analysis.

The result can then be saved locally in IndexedDB.

  • TypeScript → interface and browser integration
  • Web Worker → background processing
  • Rust and WebAssembly → log parsing and analysis
  • IndexedDB → optional local workspace history

The server delivers the page, Worker, and Wasm module. It does not receive the user-provided log or the resulting analysis.

That is the practical meaning of Local Data Custody.

The architecture is also resilient. If IndexedDB is unavailable, denied, or full, the current analysis remains usable in memory. Persistence improves the workspace, but it is not required for the analyzer to function.

Privacy through operator non-possession

Most privacy conversations begin after collection.

They ask:

  • How is the data encrypted?
  • Who can access it?
  • How long is it retained?
  • Which subprocessors receive it?
  • Can the user request deletion?
  • What happens during a breach?

Those are important questions, but they begin after the largest architectural decision has already been made.

The system took possession of the data.

Local Data Custody starts one step earlier:

Does the operator need to possess this data in the first place?

For this article, I think of the resulting principle as operator non-possession.

A traditional privacy model says:

We collect your data and commit to protecting it.

A non-possession model says:

We designed the application so that we do not receive the protected data.

The second claim is narrower, but structurally stronger.

The safest customer dataset during a server breach is the one that was never stored on the server.

The simplest tenant-isolation problem is the one that does not exist.

The easiest retention policy to enforce is for data the operator never retained.

This is consistent with the broader principle of data minimization. In practice, data minimization is often interpreted as collecting fewer fields, retaining them for less time, or limiting who can access them.

Local Data Custody asks whether collection can be removed from the architecture entirely for a particular class of data.

That does not automatically make the application secure. It removes one category of centralized exposure.

The browser is more capable than we treat it

The browser is still commonly treated as a temporary frontend.

The server owns the data. The browser displays it.

That remains the correct model for many applications, particularly those that require shared records, commerce transactions, collaboration, centralized authorization, audit history, or seamless cross-device access.

But the browser can now do considerably more than display server state.

IndexedDB provides structured local persistence.

Web Workers allow expensive processing to run away from the main UI thread.

WebAssembly provides a compilation target for languages such as Rust and makes substantial local processing practical.

Together, those capabilities create an architectural middle ground between a temporary webpage and a cloud-backed application.

The browser can act as a persistent private workspace delivered through the web.

For the log analyzer, Rust and WebAssembly matter because they allow serious parsing work to remain local. The source log is passed to the processing engine, analyzed inside the browser, and returned as a compact result.

The Web Worker keeps that processing away from the main interface.

IndexedDB allows the workspace to survive a refresh or browser restart.

None of those technologies is the architecture by itself. The architecture comes from how their responsibilities are combined.

Local processing is not automatically slow

One reason developers move work to a server is the assumption that the browser cannot handle it.

That assumption is increasingly outdated.

A server may have more raw compute capacity, more memory, and a native runtime. But a server-based workflow also requires the source data to cross the network:

Read file → upload → network latency → server scheduling → process → serialize result → download result → render

The local flow is shorter:

Read file → process locally → render

A native server parser might outperform browser Wasm in an isolated CPU benchmark.

That does not automatically make the complete server workflow faster.

For a large file, the upload may take longer than the local analysis. Server queueing, serialization, and result transfer add more overhead.

The useful claim is not that WebAssembly always outperforms a server.

It is that local processing can provide competitive or lower end-to-end latency because the data is processed where it already resides.

In this case, privacy and performance do not need to be opposing goals.

The implementation still matters. Moving inefficient code into Rust does not make it efficient through some ceremonial exchange of file extensions.

The Asyncronaut analyzer transfers the source to the Worker as a coarse unit, performs the analysis there, and returns a compact result. It avoids repeatedly moving individual lines between JavaScript and Wasm or materializing more browser objects than the UI needs.

WebAssembly provides the local processing capability.

The surrounding design determines whether that capability is used well.

IndexedDB as an application database

IndexedDB is frequently treated as an offline cache.

It can serve a more meaningful role.

In the analyzer, it allows recent workspaces to survive refreshes and browser restarts without creating a backend account or server-side database record.

The browser can retain:

  • The original source log
  • The compact analysis result
  • File metadata
  • Parser and schema versions

That avoids building backend infrastructure whose only purpose would be retaining the user’s private workspace:

  • File storage
  • Workspace tables
  • Account authorization
  • Retention jobs
  • Tenant isolation
  • Backups of uploaded logs

This is where IndexedDB becomes more than a cache.

It becomes the application database for a workspace that belongs in the browser.

There are real tradeoffs.

Browser storage can be cleared or evicted. It does not automatically follow the user to another device. A domain change can make existing data inaccessible to the new origin.

Local persistence should not be presented as permanent storage.

If the work has long-term value, export, import, deletion controls, and clear storage messaging become part of the product design.

Local custody does not remove responsibility. It changes which responsibilities the application owns.

What the architecture does not guarantee

The application operator still controls the JavaScript and WebAssembly delivered to the browser.

A future deployment could theoretically introduce an upload path. A compromised dependency, third-party script, browser extension, or XSS vulnerability could also expose locally held data.

There is currently no browser indicator comparable to the HTTPS lock that proves an application is operating locally and cannot transmit the user’s data. The user still has to trust the code being delivered.

Local Data Custody is therefore not a cryptographic guarantee that the operator could never access the data.

It is an architectural property of the current implementation.

That property should be supported by practical controls:

  • Minimal third-party code
  • A restrictive Content Security Policy
  • No session replay in protected workspaces
  • Separation between protected data and analytics
  • Safe error handling
  • Narrow network destinations
  • Automated tests that inspect outbound requests
  • Clear local deletion controls

The current Asyncronaut analyzer contains no upload or telemetry path for user-provided logs or their analysis results.

That is meaningful, even though it is not an absolute guarantee against every possible browser or supply-chain compromise.

Where this approach fits

Local Data Custody works best when an application helps users process private information but does not fundamentally require the operator to own it.

Developer tools are an obvious candidate. Logs, source code, payloads, configuration files, and diagnostic exports often contain information users may not be comfortable uploading to an unfamiliar service.

The same reasoning can apply to:

  • Document converters
  • CSV and spreadsheet analyzers
  • Code-analysis utilities
  • Image and media processors
  • Private writing tools
  • Data-anonymization utilities
  • Configuration workspaces
  • Temporary enterprise-analysis tools

It is a poor fit when the product fundamentally requires shared or authoritative server state.

A commerce transaction needs server-side validation and persistence. A collaborative document needs synchronization. A regulated system may need centralized records. Cross-device access requires the data to exist somewhere both devices can reach.

The argument is not that local is always better than cloud.

The argument is that cloud custody should be an explicit requirement, not the automatic result of needing persistence or computation.

Data custody should be a deliberate decision

I do not think Local Data Custody is a newly discovered architecture.

Unhosted applications, local-first software, local-only tools, data minimization, and client-side processing have already explored much of this territory.

My take is that custody itself deserves to be a first-class architecture question in ordinary web development.

We normally approach privacy like this:

Collect the data → secure it → restrict access → define retention → support deletion

Browser-local data custody starts earlier:

Determine what the product actually needs → keep protected data on the device → process it locally → avoid unnecessary collection

Instead of asking how to safely store a Salesforce debug log on a server, ask why the server needs the log.

Instead of requiring an account solely to preserve an analysis, ask whether local persistence and export are enough.

Instead of uploading a large file because that is the familiar architecture, ask whether the browser can perform the work itself.

The underlying technologies are not new.

What feels underused is the decision framework.

The browser does not need to be either temporary or a thin client for the cloud. It can also be a persistent, high-performance private workspace delivered through the web.

The provider delivers the capability.

The browser owns the workspace.

As users are asked to paste more logs, code, documents, and business information into web applications, that distinction becomes increasingly important.

The best privacy control may not always be a stronger promise about how collected data will be handled.

Sometimes it may be designing the application so the protected data never needs to be collected in the first place.