Deno Runtime
Build secure TypeScript-first applications with Deno runtime and its extensive standard library.
Quick Start
// deno serve — modern HTTP server
import { Hono } from "jsr:@hono/hono";
import { cors } from "jsr:@hono/hono/cors";
import { Database } from "jsr:@db/sqlite";
const db = new Database("app.db");
db.run(`CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT FALSE
)`);
const app = new Hono();
app.use("/api/*", cors());
app.get("/api/todos", (c) => {
const todos = db.query("SELECT * FROM todos").map(([id, title, completed]) => ({
id, title, completed: !!completed
}));
return c.json(todos);
});
app.post("/api/todos", async (c) => {
const { title } = await c.req.json();
db.run("INSERT INTO todos (title) VALUES (?)", [title]);
return c.json({ success: true }, 201);
});
app.patch("/api/todos/:id", async (c) => {
const id = c.req.param("id");
const { completed } = await c.req.json();
db.run("UPDATE todos SET completed = ? WHERE id = ?", [completed ? 1 : 0, id]);
return c.json({ success: true });
});
app.delete("/api/todos/:id", (c) => {
db.run("DELETE FROM todos WHERE id = ?", [c.req.param("id")]);
return c.json({ success: true });
});
// Deno.serve is built-in (no external server needed)
Deno.serve({ port: 3000 }, app.fetch);
# Run (permissions required explicitly)
deno run --allow-net --allow-read --allow-write --allow-env server.ts
# Or just use --allow-all for development
deno run -A server.ts
# Format code
deno fmt
# Lint
deno lint
# Compile to standalone binary
deno compile -A -o app-server server.ts
Key Concepts
Deno is secure by default — no file/network/env access without explicit flags. Uses web standard APIs (fetch, Request, Response). Built-in formatter, linter, test runner, and compiler. Import from URLs or JSR.
When to Use
- Building secure applications with Principle of Least Privilege
- TypeScript-first projects without configuration
- CLI tools (deno compile creates standalone binaries)
- Applications wanting web standard APIs
Step-by-Step
- Scaffold the project:
deno initcreates a standard layout with tests and config. - Pick an HTTP framework: use built-in
Deno.servefor simplicity orHonofrom JSR for routing + middleware. - Add persistence: embed SQLite via
jsr:@db/sqlite(columns map directly to TypeScript types). - Run with explicit permissions:
deno run --allow-net --allow-read --allow-write --allow-env server.ts. - Iterate with watcher:
deno run --watch server.ts, then format/lint withdeno fmt/deno lint. - Ship:
deno compile -A -o app-server server.tsproduces a standalone binary.
Examples
// Full CRUD API: server, routing, SQLite, and graceful error handling
import { Hono } from "jsr:@hono/hono";
import { cors } from "jsr:@hono/hono/cors";
import { Database } from "jsr:@db/sqlite";
const db = new Database("app.db");
db.exec(`CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT FALSE
)`);
const app = new Hono();
app.use("/api/*", cors());
app.get("/health", (c) => c.json({ status: "ok" }));
app.post("/api/todos", async (c) => {
const { title } = await c.req.json<{ title: string }>();
if (!title) return c.json({ error: "title required" }, 400);
const info = db.query("INSERT INTO todos (title) VALUES (?) RETURNING id, title, completed", [title]);
return c.json(info[0], 201);
});
app.patch("/api/todos/:id", async (c) => {
const id = Number(c.req.param("id"));
const { completed } = await c.req.json<{ completed: boolean }>();
db.run("UPDATE todos SET completed = ? WHERE id = ?", [completed ? 1 : 0, id]);
return c.json({ updated: true });
});
app.delete("/api/todos/:id", (c) => {
db.run("DELETE FROM todos WHERE id = ?", [Number(c.req.param("id"))]);
return c.json({ deleted: true });
});
Deno.serve({ port: 3000 }, app.fetch);
# Verify: start, hit endpoints, review SQLite rows
deno run --allow-net --allow-read --allow-write --allow-env server.ts
curl http://localhost:3000/api/todos
curl -X POST http://localhost:3000/api/todos -H "content-type: application/json" -d '{"title":"demo"}'
Validation
deno runworks with explicit permission flags- Deno standard library functions work correctly
deno compileproduces a working standalone binary- HTTP server responds correctly with proper permissions