neon
Safe, fast Rust bindings for building native Node.js addons
Repository Health
Technical Analysis
Neon is a Rust crate for writing native Node.js addons — modules that expose Rust functions to JavaScript through Node’s N-API, running as compiled machine code instead of interpreted JS. It wraps Node-API’s raw C bindings in a safe, ergonomic Rust abstraction layer (contexts, handles, and typed values) so addon authors get Rust’s memory safety and performance without hand-writing unsafe FFI glue.
Projects reach for Neon when a JavaScript workload needs to call into performance-critical or systems-level Rust code — parsers, codecs, cryptography, or CPU-bound computation — while still shipping as an ordinary npm package that Node.js code can require() like any other module.
What You Get
- A
Context/Handleabstraction for safely calling into and returning values from the V8/Node-API runtime - Procedural macros (
neon-macros) to export Rust functions as callable JavaScript functions - Typed wrappers for JS values (numbers, strings, objects, arrays, promises) with compile-time type checking
- An async executor bridging Rust futures/threads with Node’s event loop
- A
npm init neon@latestproject scaffolder for bootstrapping new native-addon projects - Cross-platform support for Linux, macOS, and Windows, plus experimental Bun compatibility
Common Use Cases
- Wrapping a performance-critical Rust library (parser, codec, crypto primitive) for use from Node.js
- Building an npm package backed by native code without hand-writing N-API C++ bindings
- Offloading CPU-bound computation from a Node.js service to compiled Rust for lower latency
- Reusing an existing Rust codebase inside a JavaScript/TypeScript application via native bindings
Under The Hood
Architecture: Neon’s sys module (crates/neon/src/sys) is the thin unsafe layer talking directly to Node-API’s C ABI; every other module — context, handle, object, types_impl, result, executor, thread, event — builds safe Rust abstractions on top of it, using Rust’s ownership and lifetime system to guarantee handles don’t outlive the JS scope that created them. The companion neon-macros crate generates the glue code that registers Rust functions as N-API callable entry points, so addon authors write ordinary Rust functions with a macro attribute rather than manual napi_* calls.
Tech Stack: Rust 2021 edition workspace, with libloading and linkme used for dynamic addon-registration mechanics, either for representing multiple return paths, and an optional getrandom dependency. The Node-API surface is accessed through internal sys bindings rather than a public nodejs-sys dependency (which appears only in dev-dependencies for testing on non-Windows platforms). The JS-facing tooling includes package.json/package-lock.json for the npm init neon scaffolder.
Code Quality: The workspace includes a dedicated test/ directory of member crates exercising the addon surface end-to-end, plus a bench crate for performance regression tracking. CI and lint-status badges in the README indicate enforced automated testing and linting on every change; the project also maintains a formal migration guide (doc/MIGRATION_GUIDE_1.0.0.md) documenting breaking changes across major versions, a sign of deliberate API-stability discipline.
API Design: The Context/Handle<'_, T> pattern ties every JS value handle to a lifetime scope, so the type system — not runtime checks — prevents handles from escaping their valid context, a deliberate trade against raw N-API’s manual lifetime management. Getting started still requires learning Neon’s specific vocabulary (contexts, handles, the #[neon::export]-style macros) before writing a first addon, though the npm init neon@latest scaffolder and dedicated docs site substantially shorten that ramp-up.
Used by 2 apps in this directory
Continue
Developer Tools · AI Development · AI Code Assistants
Open-source coding agent for VS Code, JetBrains, and CLI with support for 30+ LLM providers.
PostgresML
Databases · AI Development
Run ML training and LLM inference natively inside PostgreSQL with GPU acceleration — no data movement required.