Back to blog
June 18, 2026

Never Lose an Interview: Resilient Video Uploads from the Browser

Candidates record proctored video interviews on flaky laptops and flakier Wi-Fi. Here is the IndexedDB + Web Worker + resumable-upload pipeline that stopped us from losing recordings.

frontendreliabilityweb-workers

Never Lose an Interview: Resilient Video Uploads from the Browser

A candidate finishes recording their interview answers, the Wi-Fi drops on the last chunk of a 100MB+ upload, and the recording is gone. They did the work. We dropped it. In a hiring product there is no apology that fixes this — the interview cannot be un-lived, and asking someone to re-record it tells them exactly how much your infrastructure respects their time.

At Navero, candidates record video interview answers directly in the browser — camera, microphone, and sometimes a screen share — so this worst-case failure is the one we engineered the entire upload pipeline around making impossible.

The Problem

Browser recording is hostile territory:

  • The candidate closes the tab or the laptop lid mid-upload
  • Wi-Fi drops on the last chunk of a 100MB+ recording
  • Keeping recorded blobs only in memory means one refresh destroys them
  • WebM files produced by MediaRecorder have broken duration metadata, so playback seeking fails downstream
  • Naive retry loops spam the candidate with error toasts while silently going nowhere

A plain fetch upload in the page's main thread fails on every one of these.

The Solution: Persist First, Upload Off-Thread, Resume Forever

We rebuilt the pipeline around one principle: the recording is safe the moment it exists, not the moment it is uploaded.

MediaRecorder chunks
      |
      v
IndexedDB (persisted as recorded — survives refresh and crash)
      |
      v
Global upload manager (singleton, owns all upload state)
      |
      v
Web Worker (uploads off the main thread, UI stays responsive)
      |
      v
Resumable upload session to cloud storage via presigned URLs
      (interrupted uploads continue from the last acknowledged byte)

The details that made it production-grade:

  • Exponential backoff, bounded. Failed chunks retry with increasing delays up to 5 attempts.
  • Retryable versus permanent. Exhausted uploads move to a distinct permanently-failed bucket instead of looping forever — surfaced on a dedicated retry page where the candidate can re-attempt with one click.
  • Toast throttling. Transient network errors are batched and de-duplicated so a flaky connection produces one calm message, not a notification storm.
  • Metadata repair. WebM duration headers are fixed client-side before upload, so every stored recording is seekable.

Key Lessons

Durability before transport. Writing chunks to IndexedDB as they are recorded turns "the upload failed" from a data-loss incident into a retry.

The main thread is not where uploads live. A Web Worker keeps a multi-hundred-megabyte upload from janking the interview UI the candidate is still using.

Name the terminal state. Distinguishing permanently-failed from retrying made both the code and the support conversations simpler — there is always a truthful answer to "where is my recording?"

Resumable beats restartable. Continuing from the last acknowledged byte is the difference between an invisible blip and re-uploading 100MB on hotel Wi-Fi.

Results

  • Recordings survive tab closes, refreshes, and network loss — the candidate can come back and resume
  • Uploads run entirely off the main thread; recording UI stays responsive during transfer
  • Every recording ends in an explicit state: uploaded, retrying, or permanently failed with a one-click recovery path