fs is Node.js's built-in module for file system operations, offering low-level access with callback, sync, and promise-based APIs. fs-extra extends fs with additional high-level utilities like recursive copy, directory creation, and JSON helpers, while providing native promise support. fs-extra-promise was a wrapper that added promise support to older versions of fs-extra, but it is now deprecated and should not be used in new projects.
When building Node.js applications that interact with the file system β whether itβs reading configs, writing logs, or managing uploads β choosing the right tooling matters. The built-in fs module is always available, but many developers reach for higher-level packages like fs-extra or (historically) fs-extra-promise. Letβs compare them head-to-head from a practical engineering standpoint.
fs is Node.jsβs native file system module. It provides low-level access to file operations with both callback-based and synchronous APIs. As of Node.js v10+, it also includes promise-based versions under fs.promises.
// fs: Callback style
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// fs: Promise style (Node.js >=10)
const { readFile } = require('fs').promises;
const data = await readFile('file.txt', 'utf8');
fs-extra extends fs with additional convenience methods (like copy, remove, ensureDir) and automatically promisifies all functions, so every method returns a promise without needing .promises.
// fs-extra: All methods are promise-friendly by default
const fse = require('fs-extra');
const data = await fse.readFile('file.txt', 'utf8');
await fse.ensureDir('./logs'); // creates dir if missing
await fse.copy('./src', './dest'); // recursive copy
fs-extra-promise was created as a wrapper around fs-extra to add explicit promise support before fs-extra did so natively. However, this package is now deprecated.
β οΈ Important: According to its npm page,
fs-extra-promiseis no longer maintained and explicitly states: "This package is deprecated. Use fs-extra directly instead."
// fs-extra-promise: Deprecated pattern (do not use in new code)
const fsep = require('fs-extra-promise');
// This just wraps fs-extra β redundant since fs-extra supports promises out of the box
Need to create nested directories or delete entire folders? fs requires manual recursion or external logic, while fs-extra handles it natively.
// fs: Manual effort for deep mkdir
const fs = require('fs');
fs.mkdirSync('./a/b/c', { recursive: true }); // supported since Node.js v10.12.0
// But for older versions or more complex cases, youβd need custom code
// fs-extra: Simple and consistent
const fse = require('fs-extra');
await fse.ensureDir('./deeply/nested/path'); // works everywhere
await fse.remove('./folder'); // deletes recursively, even if non-empty
Note: Modern fs does support { recursive: true } in mkdir and rm (since Node.js v14.14.0), but fs-extraβs ensureDir and remove remain more ergonomic and backward-compatible.
Copying a directory tree is non-trivial with raw fs. Youβd need to walk the tree manually.
// fs: No built-in copy for directories β you must implement it
// (omitted for brevity β itβs dozens of lines)
// fs-extra: One-liner
await fse.copy('./source', './backup');
This alone makes fs-extra compelling for scripts, build tools, or CLI apps.
Both fs and fs-extra let you read/write JSON, but fs-extra adds dedicated helpers:
// fs: Manual parse/stringify
const data = JSON.parse(await fs.promises.readFile('config.json', 'utf8'));
await fs.promises.writeFile('output.json', JSON.stringify(data, null, 2));
// fs-extra: Built-in
const data = await fse.readJson('config.json');
await fse.writeJson('output.json', data, { spaces: 2 });
Less boilerplate, fewer try/catch blocks for parse errors (it throws cleanly).
Early Node.js only offered callbacks. Developers used libraries like bluebird to promisify fs. Then fs-extra emerged, offering extra methods and promise support via optional wrappers.
Eventually, fs-extra baked in promise support by default (starting around v6+). This made fs-extra-promise obsolete β it was just an unnecessary layer.
Today:
fs.promises gives you native promises, but only for standard fs methods.fs-extra gives you promises plus utility methods (copy, move, emptyDir, etc.).fs-extra-promise adds nothing new and is deprecated.The fs-extra-promise npm page clearly states:
"This package has been deprecated. fs-extra now includes promise support by default. Please use fs-extra directly."
Do not use fs-extra-promise in any new project. If you find it in legacy code, replace it with fs-extra and remove the extra dependency.
Youβre on Node.js 18+ and just need to read a JSON config file.
fs.promisesimport { readFile } from 'fs/promises';
const config = JSON.parse(await readFile('app.json', 'utf8'));
You need to empty a dist/ folder, copy static files, and ensure log directories exist.
fs-extraemptyDir, copy, and ensureDir save dozens of lines of error-prone code.import fse from 'fs-extra';
await fse.emptyDir('dist');
await fse.copy('public', 'dist');
await fse.ensureDir('logs');
You inherit a codebase using require('fs-extra-promise').
fs-extra and remove the deprecated package.| Feature | fs (native) | fs-extra | fs-extra-promise |
|---|---|---|---|
| Promise support | β
via fs.promises | β built-in | β (but redundant) |
| Recursive mkdir/rm | β (Node.js β₯10/14) | β
(ensureDir, remove) | β
(via fs-extra) |
| Directory copy/move | β | β | β
(via fs-extra) |
| JSON helpers | β | β
(readJson, etc.) | β
(via fs-extra) |
| Maintenance status | β (core Node.js) | β actively maintained | β deprecated |
| Extra dependencies | β | β (minimal) | β + deprecated wrapper |
fs when youβre in a modern Node.js environment and only need basic file operations. Itβs lightweight and dependency-free.fs-extra when you want productivity boosts like recursive copy, safe directory creation, or JSON helpers β especially in scripts, CLIs, or tooling.fs-extra-promise β itβs deprecated and offers no advantage over plain fs-extra.In most real-world Node.js projects beyond trivial examples, fs-extra pays for itself in reduced code complexity and improved reliability. Just remember: itβs a Node.js-only library, so donβt try to bundle it for the browser.
Choose fs if you're working in a modern Node.js environment (v10+) and only need standard file operations like reading, writing, or deleting files. It requires no dependencies and integrates directly with Node.js core, making it ideal for minimal, performance-sensitive applications where you don't need convenience methods.
Choose fs-extra when you need robust, high-level file system utilities such as recursive directory copying, safe directory creation (ensureDir), or built-in JSON reading/writing. Itβs particularly valuable in scripts, build tools, CLI apps, or any scenario where reducing boilerplate and handling edge cases (like missing parent directories) matters. All methods return promises by default, simplifying async code.
Do not choose fs-extra-promise for any new project. It is officially deprecated, as fs-extra has included native promise support since version 6. Using it adds an unnecessary dependency and increases maintenance risk. If encountered in legacy code, migrate to fs-extra directly.
This package name is not currently in use, but was formerly occupied by another package. To avoid malicious use, npm is hanging on to the package name, but loosely, and we'll probably give it to you if you want it.
You may adopt this package by contacting support@npmjs.com and requesting the name.