Nio is a small, statically typed language. It compiles your code to one native program, finds mistakes before it runs, and comes with an HTTP server, TLS and cryptography in the box.
import 'http';
import 'json';
type User {
String? id;
String name;
}
http.Response showUser(http.Request req) {
User u = { id: req.params["id"], name: "Ada" };
return http.json(200, json.toText(u));
}
http.Server app = http.server();
app.route(http.Method.GET, "/", http.Response (http.Request r) -> http.text(200, "hello"));
app.route(http.Method.GET, "/users/:id", http.Response (http.Request r) -> showUser(r));
await app.listen("0.0.0.0", 8080, null) catch e {
print(`cannot listen: ${e.message}`);
};A complete web service. nio build --release server.nio turns it into a single file you can copy to any server.
The things Nio is built to do well.
Nio compiles through LLVM to one native executable. There is no virtual machine and nothing to install where it runs. Release builds optimize the whole program, runtime included.
Every value is checked before the program runs. Numbers never change type on their own, and a String is never null: a value that can be missing is a String?, and you must check it first.
The compiler works out which functions can fail. Errors go up to the caller by themselves, and you handle them with catch where it makes sense. No exceptions and no hidden jumps.
async and await let one program serve many connections at once, while it waits for the network, the disk or a timer. There are no threads, so there are no locks and no data races.
An HTTP server and client, TLS 1.3, cryptography, JSON, sockets, files, processes and regular expressions are all in the standard library. You need no packages to start.
Each value uses only its own width, so a byte[] takes one byte per element. The garbage collector gives memory back to the system when the program goes quiet.
TLS checks certificates unless you say not to. Regular expressions run in linear time. Packages are checked against a hash on every build and never run code when you install them.
A formatter, a test runner, a documentation viewer, debugger support and a language server for your editor all come in the one nio command. You only need clang.
The same small programs written in Nio, C, Go and Node.js, line for line, each checked to print the same result before it is timed.
Lower is better. Wall clock, median of 9 runs.
loops100 million loop steps over an arrayfibrecursive function callsprimesinteger division and comparisonsmandelbrotfloating-point mathrecordsallocating 2 million recordsstringsbuilding and comparing stringsfilesfile I/O and regular expressionsMeasured on Apple M4 (10 cores), macOS, clang 21, Go 1.26, Node.js 24, with the scripts in the Nio repository's benchmark folder. Nio and C are compiled with -O2. These are small programs that each stress one thing, so a real application will differ. In the HTTP test the load generator runs on the same machine as the server. The Go server uses all 10 cores, while the Nio and Node.js servers use one, so Go (1 core) is the like-for-like comparison.
Records turn into JSON and back with one call. A field that can be missing says so in its type, and the compiler does not let you use it before you check it. A function that can fail needs no special signature: its errors go up to the caller, and catch handles them where you choose.
import 'fs';
import 'json';
import 'string';
type Config {
String host;
int port;
String? name; // may be missing: the compiler makes you check
}
Config load(String file) {
byte[] raw = fs.readFile(file); // can fail: the error goes up
return json.parse(string.fromByteArray(raw)) as Config;
}
Config? cfg = load("config.json") catch null;
if (cfg != null) {
print(`${cfg.host}:${cfg.port}`); // localhost:8080
}The compiler is written in Nio, and clang is the only thing it needs. It runs on macOS, Linux and Windows.
nio run app.nioCompile and run in one step while you work.
nio build --release app.nio -o appBuild an optimized native program.
./appCopy the one file to a server and run it.