Back to blog
Engineering·4 min read

How we built crash-safe recording with IndexedDB

Browsers crash. Tabs get killed. We write audio chunks to IndexedDB every few seconds so your recording survives no matter what.


The single worst thing a recorder can do is lose your audio. A 45-minute podcast interview, gone because Chrome ran out of memory in another tab. We decided early that crash safety was not a feature. It was the baseline.

The problem with in-memory recording

Most browser-based recorders work like this: they capture audio data into a growing buffer in memory. When you click stop, they assemble the buffer into a file and offer a download. This approach has a fatal flaw: if anything goes wrong before you click stop, everything is gone.

The list of things that can go wrong is long:

  • Chrome runs out of memory because of another tab
  • The OS kills the browser to reclaim resources
  • Your laptop battery dies
  • You accidentally close the tab
  • The page crashes due to a JavaScript error
  • Your cat walks across the keyboard

Every one of these scenarios results in total audio loss with a traditional in-memory recorder. The recording exists only in RAM until the explicit save step. No RAM, no recording.

Our approach: incremental writes to IndexedDB

Instead of accumulating audio data in memory and writing it to a file at the end, we flush chunks to IndexedDB on a regular interval. Every few seconds, the current buffer gets serialized and stored. If the browser crashes, the tab gets killed, or the user accidentally closes the window, the worst case is losing the last few seconds.

The flow looks like this:

  1. Audio data comes in from the MediaRecorder API
  2. We buffer a few seconds of data in memory
  3. On a timer, we write the buffered chunk to an IndexedDB transaction
  4. The in-memory buffer resets
  5. Repeat until recording stops

When you reopen Orec after a crash, it detects the incomplete session and offers to recover it. No prompts, no "are you sure" dialogs during recording. Recovery happens after the fact, cleanly.

The tricky part: reassembly

The writes themselves are not the hard part. IndexedDB transactions are fast enough for audio-sized blobs. The tricky part is reassembly.

Audio codecs expect continuous streams, and splicing chunks back together without audible glitches requires care around codec frame boundaries. We align our chunk boundaries to Opus frame sizes (20ms) so recovered audio plays back without pops or gaps.

This means:

  • No audible seams between chunks during normal playback
  • No pops or clicks at recovery points after a crash
  • Bit-accurate reconstruction of the original audio stream

Why IndexedDB and not the filesystem

The File System Access API exists, but it requires an explicit user permission prompt and is not supported in all browsers. IndexedDB is available everywhere, requires no permission prompt, and can store gigabytes of data. For a tool that needs to work instantly with zero friction, IndexedDB is the right choice.

The storage limits are generous. Chrome allows at least 60% of available disk space for a single origin. On a laptop with 256GB of storage, that is over 100GB of IndexedDB space. You would need to record continuously for days to hit that limit.

The result

The save button in Orec is mostly ceremonial. Your audio is already safe. The moment you start recording, data is flowing to persistent storage. The moment you stop, the complete recording is already on disk. The download step just packages what is already there.

This is the kind of infrastructure that nobody notices when it works. And that is the point. You should never have to think about whether your recording is safe. It just is.

Frequently
asked questions.