This page lists the settings that change Elide’s speed and memory use, and how to measure them.
| Setting | Applies to | Default |
|---|---|---|
--contexts=N, --contexts=auto | Fetch-handler servers under run, serve, dev (Linux for more than one) | 1 |
engine.contexts in elide.pkl | elide serve, elide dev | 1 |
--max-mem=SIZE | Every command | 4g for one-shot runs; sized from host memory for serve, dev |
--transport=VALUE, ELIDE_TRANSPORT_V2 | fetch and dependency downloads | auto |
--sandbox=PROFILE | Every program | trusted |
Add serving contexts
A context is one copy of your app with its own module state. Each context runs requests on its own thread, so more contexts serve more requests at once on more cores.
elide serve --no-tui --contexts=4 server.mjs
elide run --contexts=auto server.mjsauto uses the physical cores minus two. Set it per project for serve and dev:
// elide.pkl
amends "elide:project.pkl"
engine {
contexts { spawn = "auto"; reserve = 2; min = 1; max = 16 }
}| Rule | Detail |
|---|---|
elide run | Reads --contexts only; pass the flag. |
| Module state | Not shared between contexts; keep shared state in a database or another service. |
node:http servers | One context; a second copy fails with EADDRINUSE. |
| Platforms | More than one context requires Linux. |
Server I/O threads follow the context count; ELIDE_HTTP_NATIVE_WORKERS does not change them under run, serve or
dev. Field reference: Engine contexts; walkthrough:
Several contexts.
Cap memory
elide --max-mem=512m run app.js
elide --max-mem=2g serve server.mjs--max-mem caps the heap. One-shot runs (run, a bare file) default to at most 4g; serve and dev size the heap
from host or container memory, so set it on every container or shared host. A full heap exits 1 with
the heap address space is exhausted; a cap of 128m or less fails at startup. See
Troubleshooting.
Choose a network transport
--transport picks how fetch and dependency downloads reach the network. It does not change HTTP servers.
| Value | Use |
|---|---|
auto | Best transport for the host. On Linux this is v2 with epoll. |
v2 | Elide’s own transport, with its own TLS. ELIDE_TRANSPORT_V2=1 selects it when no flag is given. |
epoll, io_uring | v2 with that Linux event driver. |
kqueue | v2 on macOS; other platforms exit 2. |
nio | Portable transport, for comparison or when a native driver fails. |
elide --transport=io_uring run client.mjs
elide infoelide info prints the selected transport and driver on its Transport: line. An explicit --transport wins over
ELIDE_TRANSPORT_V2. ELIDE_TRANSPORT_DIAGNOSTICS=1 prints transport statistics to stderr.
Pick an execution profile
| Profile | Status |
|---|---|
--sandbox=trusted | Default; no confinement cost. |
--sandbox=sandboxed | Exits 2: --sandbox= |
--sandbox=isolated | Exits 2: --sandbox= |
Permission flags and limits are on Sandbox and Limits.
Find the slow part
| Question | Tool |
|---|---|
| Where does startup time go? | ELIDE_ prints each startup phase with a timestamp to stderr. |
| Which functions run most? | elide run --profiler=; see Debugging. |
| What happened during a run or a request? | elide --jfr=; see Monitoring and Profiling. |
| Where does compiled code spend CPU time? | --jitdump=DIR with Linux perf; see Monitoring and Profiling. |
| Which requests are slow in production? | Server spans and http.; see OpenTelemetry. |
Measure startup
Run hyperfine with -N (no shell) so each sample is one process:
// hello.js
console.log("Hello, world!");hyperfine -N --warmup 10 --runs 100 --export-json startup.json \
'elide run hello.js' 'node hello.js' 'bun hello.js' 'deno run hello.js'Call each runtime’s real binary: a version-manager shim or wrapper script adds a process to every sample. Give the full
path if which elide is not the installed binary.
Measure serving
Serve one fixed response and load it with wrk:
// server.mjs
export default {
hostname: "127.0.0.1",
port: 3000,
fetch() {
return new Response("Hello, world!");
},
};elide run server.mjs &
wrk -t12 -c256 -d5s http://127.0.0.1:3000/ > /dev/null
wrk -t12 -c256 -d10s --latency http://127.0.0.1:3000/ > elide.txt
kill %1| Step | Why |
|---|---|
| Discard a 5-second run first | The first requests compile the handler. |
Pin the server and wrk to separate cores, e.g. taskset -c 0-7 elide run server. and taskset -c 8-15 wrk ... | Keeps the load generator from taking the server’s CPU. |
Repeat with --contexts=auto | One context uses one thread for your handler. |
Compare Requests/sec and the --latency percentiles | Averages hide tail latency. |
bun server.mjs serves the same file; deno serve --port 3000 --host 127.0.0.1 server.mjs needs the address on the
command line.
Multi-context serving
elide run --contexts=auto server.mjs
# Or choose the count explicitly:
elide run --contexts=24 server.mjsOne process evaluates the server entry module in each context and serves requests concurrently.
Each context has its own JavaScript globals and module state. The process shares one managed heap,
garbage collector, and eligible parsed/JIT-compiled code across contexts. Ordinary objects are not shared
application state; use external coordination when replicas must agree. Process failures and GC pauses
can affect all contexts. Start with auto, then measure your workload before choosing a fixed count.
The published HTTP benchmarks distinguish default single-context
serving from tuned multi-context serving with HTTP pipelining, and include a configuration table,
architecture diagram, hardware/OS details, and a downloadable runner. Their peak configuration also
selects inline scheduling and io_uring; --contexts alone does not reproduce it.
See also
- Compatibility Matrix for API coverage per release
- Changelog for performance changes per release