Deno Cheat Sheet
Deno runtime essentials: permissions flags, built-in tooling, npm/JSR imports, and the standard library APIs for common tasks.
Running & Permissions
Deno is secure-by-default; explicitly grant only the permissions a script needs.
deno run app.ts # no permissions granteddeno run --allow-net --allow-read app.tsdeno run -A app.ts # allow-all (dev only)deno run --allow-net=api.example.com:443 fetcher.ts # scoped permissiondeno compile --allow-net -o myapp app.ts # single self-contained binarydeno test --allow-read # run testsdeno fmt # built-in formatterdeno lint # built-in linter
Imports: npm, JSR, and URLs
Deno resolves npm: and jsr: specifiers natively, alongside direct URL imports.
import { serve } from "jsr:@std/http/server";import express from "npm:express@4";import { z } from "npm:zod@3";// deno.json import map keeps specifiers short// {// "imports": { "std/": "jsr:/@std/" }// }import { join } from "std/path/mod.ts";
Native HTTP Server
Deno.serve is the built-in, zero-dependency way to handle HTTP requests.
Deno.serve({ port: 8000 }, (req) => { const url = new URL(req.url) if (url.pathname === "/api/health") { return new Response(JSON.stringify({ ok: true }), { headers: { "content-type": "application/json" }, }) } return new Response("Not Found", { status: 404 })})
Deno KV
Built-in transactional key-value database, no external dependency required.
const kv = await Deno.openKv()await kv.set(["users", "u1"], { name: "Ana" })const entry = await kv.get(["users", "u1"])console.log(entry.value) // { name: "Ana" }const atomic = kv.atomic()atomic.check({ key: ["users", "u1"], versionstamp: entry.versionstamp })atomic.set(["users", "u1"], { name: "Ana", age: 31 })await atomic.commit()
Common CLI Flags & Config
Frequently needed permission and config flags.
- --allow-net[=hosts]- network access, optionally scoped to a comma-separated host list
- --allow-read[=paths] / --allow-write[=paths]- filesystem access, optionally scoped
- --allow-env[=vars]- environment variable access
- --watch- restart the process on file change (deno run --watch app.ts)
- deno.json / deno.jsonc- project config: import maps, compiler options, tasks
- deno task <name>- run a script defined under `tasks` in deno.json, like npm scripts
WebSocket Upgrade in Deno.serve
Deno.upgradeWebSocket turns an incoming HTTP request into a WebSocket connection without any extra library.
Deno.serve((req) => { if (req.headers.get("upgrade") !== "websocket") { return new Response("Expected WebSocket", { status: 400 }) } const { socket, response } = Deno.upgradeWebSocket(req) socket.onopen = () => console.log("client connected") socket.onmessage = (e) => socket.send(`echo: ${e.data}`) socket.onclose = () => console.log("client disconnected") return response})
FFI with Deno.dlopen
Call into a native shared library directly, useful for wrapping C/Rust code without writing a Node native addon.
const lib = Deno.dlopen("./libadd.so", { add: { parameters: ["i32", "i32"], result: "i32" },})console.log(lib.symbols.add(2, 3)) // 5lib.close()// run with: deno run --allow-ffi --unstable-ffi ffi.ts
Test Steps & Resource Sanitizers
Deno.test verifies no leaked async ops/resources by default, and supports nested named steps for structuring long tests.
Deno.test("user workflow", async (t) => { await t.step("create user", async () => { const res = await fetch("http://localhost:8000/users", { method: "POST" }) if (res.status !== 201) throw new Error("expected 201") }) await t.step("fetch user", async () => { const res = await fetch("http://localhost:8000/users/1") if (!res.ok) throw new Error("fetch failed") })})// disable leak checks only when intentional (rare):// Deno.test({ name: "noisy", sanitizeResources: false, fn: async () => {} })
Deno.cron & Queues
Deno Deploy supports scheduled jobs and a durable queue backed by Deno KV, without a separate infra service.
Deno.cron("nightly cleanup", "0 2 * * *", async () => { const kv = await Deno.openKv() for await (const entry of kv.list({ prefix: ["sessions"] })) { if (isExpired(entry.value)) await kv.delete(entry.key) }})const kv = await Deno.openKv()await kv.enqueue({ type: "send-email", to: "[email protected]" }, { delay: 5000 })kv.listenQueue(async (msg) => { if (msg.type === "send-email") await sendEmail(msg.to)})
Lesser-Known Runtime APIs
Built-ins that replace common npm dependencies.
- Deno.Command- spawn subprocesses (replaces child_process.spawn/exec)
- Deno.watchFs()- native filesystem watcher, async iterable of FS events
- Deno.permissions.query()/.request()- inspect or prompt for a permission at runtime instead of failing
- import.meta.main- true only when the module was the entry point, useful for dual lib/CLI files
- Deno.env.toObject()- snapshot all environment variables at once
- Deno.readTextFileSync / writeTextFileSync- synchronous file I/O for CLI tooling where async isn't worth it
Use scoped permissions (`--allow-net=api.example.com`, `--allow-read=./data`) rather than `-A` in anything beyond local prototyping — Deno's whole security model is undermined the moment you reach for allow-all, including in CI.