Technical Deep-Dive

How Qinsio processes 50,000 rows in under 5 seconds

Everything runs inside your browser. No server. No upload. This page explains exactly how — the data structures, the algorithms, and the architectural decisions that make it fast.

O(n)
Deduplication complexity
0
Bytes sent to server
2
JS threads used
Each cell is parsed

Architecture overview

Two threads, five pipeline stages, zero server round-trips.

Main Thread (UI)
  • Renders progress bar
  • Accepts file drops
  • Shows column mapping UI
  • Triggers browser download
Worker Thread (Engine)
  • Parses CSV / XLSX
  • Normalises every cell
  • Builds hash map, finds duplicates
  • Detects mismatches
  • Serialises + compresses XLSX output
Message flow
UI──▶postMessage( type: "parse", file )
Worker──▶postMessage( type: "progress", percent: 0→100 )
Worker──▶postMessage( type: "parse-result", parsedA )
↳ UI shows column mapping, user clicks "Find Duplicates"
UI──▶postMessage( type: "process", parsedA, mappings )
Worker──▶postMessage( type: "process-result", exportBlob )

The processing pipeline

Five stages, each executed once per run, each designed to minimise repeated work.

PHASE 01File Read

Browser-native file parsing

Your file is read directly via the FileReader API — no upload, no network request. CSV files are parsed with PapaParse's streaming tokeniser. XLSX files are parsed with SheetJS. Both produce an identical internal row format.

0 bytes sent to any server
PHASE 02Normalize

Single-pass typed normalization

Every cell is classified once: number, date, boolean, or string. Dates are parsed to UTC timestamps. Numbers are stored as floats. Whitespace is trimmed. This typed representation is locked in memory and reused for every subsequent step — there is no re-parsing.

Each cell touched exactly once
PHASE 03Hash

O(n) hash-map deduplication

A composite key is built for each row by joining all its typed cell values. That key is inserted into a JavaScript Map. A Map lookup is O(1), so the full deduplication pass over n rows is O(n) — not the O(n²) of a naive pairwise comparison. For 50,000 rows: 50,000 hash operations instead of 2.5 billion comparisons.

O(n) — linear time, not quadratic
PHASE 04Compare

Key-join mismatch detection

For two-file comparison, rows from both files are indexed by their shared key columns into two Maps. A single linear scan finds rows missing in B, rows missing in A, and rows present in both with changed values — all in O(n + m) time.

O(n + m) — both files in one scan
PHASE 05Export

Compressed XLSX written in the worker

The output workbook (Clean Data, Duplicates, Invalid Rows, Executive Summary) is serialised with compression:true inside the Web Worker, then transferred to the main thread as a transferable ArrayBuffer — zero copying. Compression reduces a 50k-row file by ~3.5× before the browser even offers the download.

~3.5× size reduction via deflate

Why hash maps beat pairwise comparison

The single biggest performance decision in the engine.

✗ Naive approach — O(n²)
for row A in rows:
for row B in rows:
if A == B: mark_duplicate()

50,000 rows → 2.5 billion comparisons. A browser tab running this would freeze for minutes or crash entirely.

✓ Qinsio approach — O(n)
map = new Map()
for row in rows:
key = hash(row.cells)
map.get(key).push(row)

50,000 rows → 50,000 hash operations. Each row is touched once. Duplicates naturally land in the same bucket.

Row countPairwise O(n²)Hash map O(n)
1,0001,000,0001,000
10,000100,000,00010,000
50,0002,500,000,00050,000

Key design decisions

Every choice is deliberate and performance-motivated.

Web Worker thread isolation

All processing runs in a dedicated background thread. The main thread — which drives your UI — is never touched during computation. You can scroll, resize, or click while 50,000 rows are being hashed.

Two-phase pipeline

Phase 1 parses and normalises your file so you can configure column mappings in the UI. Phase 2 runs detection on the already-normalised data. The expensive file I/O and cell parsing happens exactly once.

Throttled progress reporting

The worker posts progress messages only every 2,000 rows and only when the percentage actually advances. Unrestricted postMessage() calls would dominate runtime on large files.

Exact matching — no probabilistic guesswork

Duplicates are found by deterministic row hashing. Mismatches are found by exact key equality. There is no fuzzy matching, no ML model, no thresholds to tune. The result is always reproducible and auditable.

Privacy is not a trade-off — it is a performance feature

Running entirely in the browser eliminates the biggest bottleneck in web applications: the network.

Traditional SaaS
  • Upload file (slow)
  • Server processes
  • Download result
  • Server stores copy
Qinsio
  • File stays on your machine
  • Worker thread processes
  • Result ready instantly
  • Nothing stored anywhere
Difference
  • 0 network round-trips
  • No upload wait time
  • No server costs
  • No data breach risk

Guarantees that don't require trust

These aren't policies you have to read or promises you have to believe. They follow directly from how the software is built — browser-only, no server, deterministic algorithms.

  • Your files never leave your browser
  • No account required
  • No AI guesses
  • No internet required after loading
  • Every result is deterministic
  • Output can be audited manually

Why we didn't use AI

Many spreadsheet tools now advertise AI. We intentionally didn't.

Finding duplicate rows doesn't require a language model. It requires deterministic algorithms. A hash map finds every duplicate, every time, in linear time — with zero probability of a hallucinated result.

That's why every Qinsio result is repeatable. The same input always produces the same output. You can verify it yourself by running the same file twice.

For accounting and finance work, determinism isn't a nice-to-have. It's a requirement.

AI approach
  • Probabilistic output
  • Different results on re-run
  • Unexplainable decisions
  • Requires server + API calls
  • Can hallucinate matches
Qinsio approach
  • Deterministic output
  • Identical results every run
  • Fully traceable row hashes
  • Runs 100% offline
  • Zero false positives

See it in action

Drop a CSV or XLSX file and watch the pipeline run. Up to 50,000 rows, entirely in your browser.

Try it now