ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 08

  1. Blog

fast-glob vs globby: 0.7 ms vs 14 ms With gitignore

Aditya Challa·5 October 2026·6 min read

Hands-on
On this page
  1. What I tested
  2. How fast is fast-glob vs globby?
  3. What does each one cost to install and bundle?
  4. Do they return the same files?
  5. Which one should you pick?
  6. Sources
  7. Related

I timed both glob libraries on this box against the same 7,782-file repo copy: with node_modules excluded by an ignore pattern, fast-glob 3.3.3 returned 481 .js files in about 0.72 ms and globby 16.2.4 in about 1.22 ms. Turning on globby's gitignore: true gave the same 481 files but took 14.3–15.9 ms, roughly 20× the fast-glob call.

Short answer: use fast-glob (or tinyglobby) when you can write the ignore list yourself, and pay for globby when you need .gitignore rules honored or directory arguments expanded. No affiliate links in this post.

What I tested

  • Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 03:00 IST.
  • Versions: fast-glob 3.3.3, globby 16.2.4, tinyglobby 0.2.17 as a third reference (all npm latest that day), Node 20.19.2, esbuild 0.28.2 node ESM minify + gzip -9.
  • Fixture: a copied Jest/Vitest test project, 7,782 files including its node_modules, plus a .gitignore listing node_modules, coverage and *.log. Two jobs: a recursive *.js match across everything (3,736 hits) and the same match with node_modules excluded (481 hits). Every library returned identical counts.
  • Timing: async API, one first call recorded separately, then the median of 31 calls, in two processes with the order reversed. A second fixture with only 400 source files checked whether the gitignore cost was a fixed overhead. Scripts and JSON in /workspace/bench-fast-glob-globby/.
  • Not tested: cold disk cache (every run after the first is page-cache warm), Windows paths, network drives, monorepos with dozens of nested .gitignore files, the stream APIs, and Node's own fs.glob, which needs Node 22.

How fast is fast-glob vs globby?

Job (median of 31, ms)Run 1Run 2Files
fast-glob, whole tree16.2715.663,736
globby, whole tree20.0418.703,736
tinyglobby, whole tree15.6714.753,736
fast-glob, node_modules ignored0.720.73481
globby, node_modules ignored1.231.22481
globby, gitignore: true14.3115.87481
tinyglobby, node_modules ignored0.871.21481

globby calls fast-glob under the hood, so on plain globbing it adds a steady 3–4 ms on the big walk and about half a millisecond on the small one. The gitignore row is the real decision. On the 400-file second fixture the numbers were 1.04 ms for fast-glob, 1.59 ms for plain globby and 12.62 ms with gitignore: true, so on this box it behaves like a fixed cost of roughly 11–13 ms per call, not something that grows with your repo. I did not profile where that time goes. For a build script that globs once, 14 ms is noise; for a watcher or a dev-server plugin that re-globs on every change, it adds up. If part of your tooling is Python, recursive file listing there is measured in glob vs rglob vs os.walk, and the raw directory-read cost underneath any glob is measured in scandir vs listdir.

What does each one cost to install and bundle?

PackageMinifiedgzipInput filesnode_modules on disk
fast-glob 3.3.382,800 B26,147 B741,304 KB
globby 16.2.4115,345 B37,736 B831,684 KB
tinyglobby 0.2.1737,763 B13,568 B9276 KB

globby includes fast-glob as a dependency, so it is always the bigger of the two: about 11.6 KB more gzip, the ignore parser, the .gitignore handling and a few small helpers. If you ship a bundled CLI, the gap is the same kind I measured for process runners in tinyexec vs execa, and you can lock it in CI the way size-limit vs bundlesize describes. tinyglobby was the smallest by far and kept pace with fast-glob in both jobs here.

Do they return the same files?

Checkfast-glob 3.3.3globby 16.2.4
Directory name as the pattern (src)0 files441 files (expands to everything inside)
src/debug.log with a .gitignore *.log rulereturneddropped with gitignore: true
Dotfiles by defaultskippedskipped
Negative pattern in the array420 files420 files
Module format / Node enginesCommonJS, Node 8.6+ESM only, Node 20+

Two rows matter in practice. globby's expandDirectories turns a bare folder name into its contents, so CLI arguments like src just work; with fast-glob you get an empty array and have to append the recursive pattern yourself. And globby is ESM only, which forces a dynamic import in an older CommonJS build script. If you are compiling that script anyway, the choice between bundlers in tsup vs unbuild handles the ESM switch. Path joining around the results is covered in pathe vs node:path, and if you are globbing to find dead files, Knip vs depcheck already does that walk for you.

Which one should you pick?

SituationMy pick
Build script with a known ignore listfast-glob
CommonJS code or Node below 20fast-glob
CLI that takes folder names and must respect .gitignoreglobby
Hot path (watcher, dev plugin) that re-globs oftenfast-glob or tinyglobby, ignore list written out
Smallest bundle for a published tooltinyglobby

Bottom line: on this box fast-glob 3.3.3 matched 481 files in about 0.72 ms, globby 16.2.4 in about 1.22 ms, and globby with gitignore: true in 14–16 ms, at a 37.7 KB versus 26.1 KB gzip bundle. Who should not switch to globby: hot paths and CommonJS projects that only need a fixed ignore list. Who should not stay on raw fast-glob: user-facing CLIs where people expect .gitignore and folder arguments to behave like git does.

How this was made: I installed all three packages on the ShopperCove box, copied a real test project as the fixture, ran each glob 31 times in two order-reversed processes, bundled each package with esbuild, and checked directory, dotfile and .gitignore behavior on the same tree. The JSON results sit next to the scripts. The write-up was drafted with AI help and checked against that output.

Sources

  • https://github.com/mrmlnc/fast-glob
  • https://github.com/sindresorhus/globby
  • https://github.com/SuperchupuDev/tinyglobby
  • https://www.npmjs.com/package/fast-glob
  • https://www.npmjs.com/package/globby
  • https://esbuild.github.io/

Related

  • https://www.shoppercove.com/blog/glob-vs-rglob-vs-walk-localhost-lab
  • https://www.shoppercove.com/blog/scandir-vs-listdir-localhost-lab
  • https://www.shoppercove.com/blog/tinyexec-vs-execa
  • https://www.shoppercove.com/blog/size-limit-vs-bundlesize
  • https://www.shoppercove.com/blog/tsup-vs-unbuild
  • https://www.shoppercove.com/blog/pathe-vs-node-path
  • https://www.shoppercove.com/blog/knip-vs-depcheck
  • https://www.shoppercove.com/blog/fnmatch-vs-re-localhost-lab
fast-globglobbytinyglobbygitignorenode.jsperformancebenchmarkingjavascript

Lab evidence

What I found running this

Hands-on on ShopperCove box 6 Oct 2026 ~03:00 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2). fast-glob 3.3.3 vs globby 16.2.4, tinyglobby 0.2.17 reference; esbuild 0.28.2 node ESM minify + gzip -9. Fixture: copied Jest/Vitest project, 7,782 files incl node_modules, .gitignore (node_modules, coverage, *.log). Recursive .js match, async API, median of 31, order-reversed (ms): whole tree 3,736 files fast-glob 16.27/15.66, globby 20.04/18.70, tinyglobby 15.67/14.75; node_modules ignored 481 files 0.72/0.73 vs 1.23/1.22 (tinyglobby 0.87/1.21); globby gitignore: true 14.31/15.87. 400-file fixture: 1.04 / 1.59 / 12.62 ms (gitignore). Bundle 82,800/26,147 B (74 inputs) vs 115,345/37,736 B (83); tinyglobby 37,763/13,568 B. node_modules on disk 1,304 KB vs 1,684 KB vs 276 KB. Behavior: globby expands a bare dir arg (src -> 441 files), fast-glob returns 0; gitignore: true drops *.log; both skip dotfiles; globby ESM-only Node 20+, fast-glob CJS Node 8.6+. Not tested: cold disk cache, Windows, network drives, many nested .gitignore files, streams, Node 22 fs.glob. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 55

    Klona vs structuredClone: 1.4M vs 225k Clones per Second

    5 Oct 2026

  • Plate 06

    oxc-parser vs @babel/parser: 9.1 ms vs 47.9 ms on 513 KB

    5 Oct 2026

  • Plate 93

    mlly vs acorn: 0.046 ms vs 0.017 ms findExports

    5 Oct 2026

On this page

  1. What I tested
  2. How fast is fast-glob vs globby?
  3. What does each one cost to install and bundle?
  4. Do they return the same files?
  5. Which one should you pick?
  6. Sources
  7. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove