BlazeDiff vs microdiff
@blazediff/object is ~9% faster
than microdiff over our 8 object shapes, and it returns the same kind of
result: a flat list of changes, each with a path. Most of that gain comes from
large arrays, identical ones above all. On small, flat objects microdiff is
faster, so check the per-fixture table for the shapes you diff.
microdiff is a tiny, zero-dependency object diff that runs everywhere. BlazeDiff
started from the same idea and adds a fixed result shape. Every entry has type,
path, value and oldValue, which keeps the V8 object shape stable in hot
loops.
At a glance
| microdiff | BlazeDiff (@blazediff/object) | |
|---|---|---|
| License | MIT | MIT |
| Size | Under 1 KB | Zero dependencies |
| Runtimes | Node, Deno, Bun, browsers | Node, Deno, Bun, browsers |
| Change types | Strings: "CREATE", "REMOVE", "CHANGE" | Numbers: 0 create, 1 remove, 2 change |
| Entry shape | value and oldValue only when relevant | Always type, path, value, oldValue |
| Cycle handling | cyclesFix (default on) | detectCycles (default on) |
| Rich types | Date, RegExp, boxed primitives, Temporal | Date, RegExp |
Benchmarks
Object (@blazediff/object vs microdiff)
TOTAL TIME Β· 8 FIXTURES Β· MEAN OF 10000 RUNS Β· IO EXCLUDED
Apple M1 Max Β· darwin/arm64 Β· Node v22.14.0 Β· rustc 1.97.1 (8bab26f4f 2026-07-14) Β· 2026-10-22 Β· 234b300-dirty Β· pnpm benchmark object
Per-fixture results (8)
| Fixture | Microdiff | BlazeDiff | BlazeDiff vs Microdiff |
|---|---|---|---|
| complex object - tag addition | 0.00ms | 0.00ms | 1.31x |
| deep nested - timeout change | 0.00ms | 0.00ms | 0.93x |
| large array - single item change | 0.27ms | 0.24ms | 1.16x |
| large identical arrays | 0.06ms | 0.00ms | 15.69x |
| large nested object - multiple small changes | 1.59ms | 1.50ms | 1.06x |
| nested object - theme change | 0.00ms | 0.00ms | 1.16x |
| simple object - age change | 0.00ms | 0.00ms | 0.58x |
| simple object - identical | 0.00ms | 0.00ms | 0.85x |
| TOTAL | 1.92ms | 1.74ms | 1.10x |
Switching
The call is the same. Compare type against numbers instead of strings.
// Before
import diff from "microdiff";
const changes = diff(oldObj, newObj, { cyclesFix: false });
const added = changes.filter((c) => c.type === "CREATE");
// After
import diff from "@blazediff/object";
const changes = diff(oldObj, newObj, { detectCycles: false });
const added = changes.filter((c) => c.type === 0);When to keep microdiff
- Bundle size is your first constraint.
- You mostly diff small, flat objects, where microdiff wins in our runs.
- You diff Temporal values.
- Your code reads the string change types and you do not want to touch it.