Multi-tenant JavaScript
Edge Runtime

One OS process. Many isolated apps on V8 isolates. Portable sliver bundles with precompiled bytecode and zero-downtime hot-swap. WinterTC compatible.

0-downtime
Hot-swap
100%
Test Pass
v2.8.0
Current

Features

Production-ready edge runtime with comprehensive API support

Precompiled Bytecode

Slivers carry V8 bytecode built at pack time, so the first request skips JavaScript parse and compile.

🔒

Multi-tenant Isolation

One OS process hosts many isolated apps in separate V8 isolates with strong per-app boundaries.

W

WinterTC Compatible

Full fetch(), Request, Response, Headers, URL, TextEncoder, TextDecoder support per WinterTC spec.

CPU Time Limits

Configurable per-request CPU limits with timer-based termination. Prevents infinite loops and resource exhaustion.

Memory Management

Per-isolate memory limits with LRU eviction and soft termination. 4-tier pressure monitoring prevents OOM conditions.

P

Per-Tenant Metrics

Automatic metrics collection per hostname. Prometheus exposition format at /_admin/metrics endpoint.

W

WebAssembly Support

V8 built-in WASM engine for executing binary modules. Source hash caching for integrity verification.

🔐

WebCrypto API

Full crypto.subtle implementation: AES-GCM, HMAC, SHA-256/384/512, PBKDF2. JWK key import/export.

S

Sliver Bundles

Portable tar bundles: app files + precompiled bytecode. Deploy once, run anywhere. Zero-downtime hot-swap on SIGHUP.

WebSocket Support v2.3.0

WebSocketPair API compatible with Cloudflare Workers. Per-connection V8 isolate with CPU/memory enforcement per frame.

Learn more →

Persistent KV Storage nano:kv

EdgeStore-backed key-value store per app. Hostname-namespaced, zero config. JSON helpers, named namespaces, prefix listing. import { kv, openKV } from 'nano:kv'

API reference →

localStorage shim

Drop-in browser localStorage API backed by nano:kv. Front-end code and Cloudflare Workers patterns using localStorage.* run unchanged — no rewrite needed.

API reference →

Node.js & Browser APIs

require('path'), require('buffer'), require('assert'), process.env, btoa/atob — common npm packages work without a bundler shim.

Compatibility matrix →
G

Google Apps Script nano:gas

Run .gs files unchanged on nano-rs. SpreadsheetApp, DriveApp, PropertiesService, Logger and more — backed by a service account.

GAS reference →

Run code written for any target

NANO speaks three dialects. Pick the one your code already uses.

WinterTC / Cloudflare Workers

Edge-native handlers

Standard fetch(), Request, Response, WebCrypto, streams. Drop-in for Workers code.

export default {
  async fetch(request) {
    const url = new URL(request.url);
    return Response.json({
      path: url.pathname,
    });
  }
};
Node.js packages

npm-compatible polyfills

require('path'), require('buffer'), require('assert'), process.env — common npm packages work without a bundler shim.

const path = require('path');
const { from } = require('buffer');

export default {
  async fetch(req) {
    const env = process.env.NODE_ENV;
    return new Response(env);
  }
};
Browser APIs + KV

Browser code + persistence

localStorage shim, nano:kv for structured storage — front-end code and Cloudflare KV patterns work without changes.

import { kv, openKV } from 'nano:kv';

const hits = (await kv.getJSON('c')) ?? 0;
await kv.setJSON('c', hits + 1);

// Or use the localStorage shim
await localStorage.setItem('theme', 'dark');
Google Apps Script

.gs files, unchanged

Set GAS_COMPAT=true and upload your .gs file. SpreadsheetApp, PropertiesService, Logger and more — backed by a service account.

async function doGet(e) {
  const sheet = SpreadsheetApp
    .getActiveSpreadsheet()
    .getActiveSheet();
  const rows = await (
    await sheet.getDataRange()
  ).getValues();
  return JSON.stringify(rows);
}

Get started

Follow the quick start guide to build and run your first NANO application.

View Quick Start Guide