Skip to main content

Command Palette

Search for a command to run...

Unlocking Native Performance in Node.js with Node-API (N-API)

Updated
4 min read
Unlocking Native Performance in Node.js with Node-API (N-API)

Node.js is fast, flexible, and great for building APIs, servers, and full-stack apps. But sometimes JavaScript isn’t enough.

  • What if you need blazing-fast performance?

  • Or you want to use an existing C/C++ library instead of rewriting it in JS?

  • Or maybe you need access to low-level system features like file systems, drivers, or hardware?

That’s where Node-API (N-API) comes in.

1.What is Node-API (N-API)?

Node-API is a stable C API for building native addons in Node.js.

Before Node-API, addons were tied directly to V8 (Node’s JavaScript engine). Every Node.js or V8 update risked breaking your addon.

With Node-API:

  • Addons work across Node.js versions.

  • It’s engine-independent (works with V8, ChakraCore, Hermes, etc.).

  • It provides a stable ABI (Application Binary Interface).

💡
Node-API is the bridge between JavaScript and native code.

2.Why Should You want N-API?

  • Future-proof - Your addon won’t break every time Node.js upgrades.

  • Performance - Run CPU-heavy tasks in native code.

  • Reuse existing libraries - Wrap C/C++ instead of reinventing in JS.

  • System access - Do things pure JS can’t (hardware, OS integration).

Popular modules that use native code:

  • bcrypt → password hashing

  • sharp → image processing

  • sqlite3 → database driver

3.How Node-API Works?

JavaScript talks to Node-API, which safely communicates with your C/C++ addon.

4.Let’s build a tiny addon

Let’s make our hand’s dirty by building a tiny addon

Step 1: Prerequisites

Make sure you have:

  • Node.js

  • Python (for build tools)

  • C++ compiler (gcc/clang/MSVC)

npm install -g node-gyp

Step 2: Addon Code (C++)

Create a new file named hello.cpp

#include <napi.h>

// This is the native C++ function that will be exposed to JavaScript.
// It takes the standard N-API CallbackInfo object and returns a Napi::Value.
Napi::Value HelloWorld(const Napi::CallbackInfo& info) {
  // Napi::Env is the environment context for the current Node.js instance.
  // It's used to create JavaScript values (strings, numbers, objects, etc.).
  Napi::Env env = info.Env();

  // Create a new JavaScript string with the value "Hello World from C++!"
  // and return it. This value will be the result of calling the function
  // from your Node.js code.
  return Napi::String::New(env, "Hello World from C++!");
}

// The Init function is the entry point for the Node.js addon.
// It's responsible for setting up the exports that will be available
// in JavaScript when the addon is required.
Napi::Object Init(Napi::Env env, Napi::Object exports) {
  // Set a property on the 'exports' object.
  // The first argument is the name of the export (how you'll call it in JS).
  // The second argument is a Napi::Function that wraps our native C++ function.
  exports.Set(Napi::String::New(env, "hello"),
              Napi::Function::New(env, HelloWorld));

  // Return the modified exports object.
  return exports;
}

// This macro registers the addon with Node.js.
// The first argument is the addon's name (must match 'target_name' in binding.gyp).
// The second argument is the initialization function we just defined.
NODE_API_MODULE(hello_world_addon, Init)

This is the core C++ source code. It defines the HelloWorld function that returns a string and an Init function that exports HelloWorld under the name hello.

Step 3: Build Config

Create binding.gyp

{
"targets": [
  {
    "target_name": "hello_world_addon",
    "sources": [ "hello.cpp" ],
    "include_dirs": [
       "<!@(node -p "require('node-addon-api').include")"
     ],
     "defines": [ "NAPI_DISABLE_CPP_EXCEPTIONS" ]
   }
 ]
}

This is a build configuration file for node-gyp. It tells the compiler which C++ files to compile (sources), what to name the final binary (target_name), and where to find the necessary header files (include_dirs).

Step 4: Build the Addon

node-gyp configure build

This generates build/Release/addon.node

Step 5: Use It in Node.js

Create index.js

const addon = require('./build/Release/hello_world_addon.node');

console.log(addon.hello()); // → "Hello from Node-API!"

Run it:

node index.js

You can find the entire source code for the helloworld addon in the following Github

5.How N-API differs from Worklets or WebAssembly?

  • Node-API → bridge to native C++ in Node.js.

  • Worklets → lightweight JS workers in browser rendering.

  • WebAssembly → portable, high-performance modules for both browser + Node.js.

6.Node-API and Hermes

Hermes — a JavaScript engine built by Meta for React Native. It’s optimized for:

  • Fast startup

  • Low memory usage

  • Small binary size

Node.js usually runs on V8, but the community has experimented with running Node.js on Hermes.

Here’s why Node-API is important:

  • Node-API is engine-independent.

  • If Node.js runs on V8, ChakraCore, or Hermes, your addon still works.

  • Without Node-API, you’d have to rewrite bindings for every engine.

Example

Think of Node-API as a universal power adapter:

  • V8 = US plug

  • Hermes = EU plug

  • ChakraCore = UK plug

Without Node-API, you’d need a different charger each time. With Node-API, your addon plugs in anywhere.

Node-API

Node-API bindings

Node-API for Hermes

More from this blog

Nidhin's blog

168 posts

✨Crafting Code with a Smile for 8 Years:) Merging the Formal Dance of Angular, the Playful Rhythms of React, and the Next-level Moves of Next.js 🚀