Deno Deploy
Subhosting Private Preview
Isolates as a Service on Deno Deploy

Short term roadmap:
- 🚧 Usage reporting
- 🚧 New cache infrastructure
Key Ideas:
- Deno Deploy handles all scaling, sandboxing and isolate execution. You integrate against a simple HTTP API
- You implement a "relay" that forwards http requests (or events), e.g: dash.deno.com/playground/sub-relay
- You implement an "origin" that responds to RPCs (boot, ...), e.g: dash.deno.com/playground/sub-origin
Implementation outline:
- You treat Deno Deploy as a stateless isolate runner with seamless scaling &
routing
(deployments are created lazily, amortized by caching to fit typical short/long tail distributions) - All authentication between you & Deno Deploy uses JWTs signed with a shared secret
- Your relay should inject an
x-deno-subhost
JWT header with the following claims:deployment_id
(unique upstream identifier) (possibly project_id/customer_id too)subhoster_id:
"acme" (JWT header kid for now, not required ATM)- An optional
rpc_root
override, default set to https://deno.acme.com/v0/ - You may also add an
x-forwarded-host
header encoding the originalhost
header (allowing N domains to map to a single deployment)
- Your relay then forwards the request to
subhosting.deno.dev
or{hash/deployment_id}-subhosting.deno.dev
(for optimized load-balancing) - Your origin may implement the following (webhook-like) RPCs, note that boot
is required:
- boot:
GET
https://deno.acme.com/v0/boot?deployment_id=...
- returns the JS Bundle or eszip payload in the body
- returns metadata like envs, etc... in a special response header
(
x-deno-config
)
- read_blob:
GET
https://deno.acme.com/v0/read_blob?deployment_id=...&file_id=...
(file IDs are typically hashes are in manifest) - read_tree:
GET
https://deno.acme.com/v0/read_tree?deployment_id=...
- report_activity?:
POST
https://deno.acme.com/v0/report_activity?deployment_id=...
- Reports logs and usage info
- boot:
- Deno Deploy sends the request through to the isolate, booting it if necessary
- Once the isolate responds, the http response is sent back to the relay (completing that request)
Specifics
Technical specifics we may need to coordinate on
Signing
All JWTs must be signed using HS256 (HMAC sha-256) using your shared secret.
Control plane errors
If there’s an error routing a request to a subhosted isolate or an error spawning it, Deno Deploy will reply with a HTTP 502 with error info. Could potentially relay this to a reporting endpoint
ESZIPs
ESZIPs are a custom bundle format built by the Deno team.
You can think of them as a mix between a lockfile and a tar-archive. Unlike regular scope-hoisted JS bundles, ESZIPs store JS module-graphs untransformed whilst also supporting JSON modules & WASM (in the future).
You can produce ESZIPs using our JS SDK, specifically using build(...), for example:
// import eszip
import { build } from "https://deno.land/x/eszip@0.15.2/mod.ts";
// root specifier(s) you want to bundle,
// these should valid URLs (file:/// or https://) or resolvable by your loader
const roots = ["https://deno.land/std/http/file_server.ts"];
// build the eszip from the roots
// NOTE: you can provide a custom loader func in the 2nd arg
const bytes = await build(roots);
// write the eszip to disk (or upload somewhere)
await Deno.writeFile("./out.eszip2", bytes);
Asset Tree Manifest
A JSON hashmap representing the file-tree available to the current deployment, it is used for readdir & stat operations. File entries in the manifest have (content addressable) IDs which are then used for (file) blob reads.
Deleting Projects
Given this stateless design we won’t persist any of your customer data/code (besides cache that will ultimately expire and usage info/logs). Inactive isolates will be automatically terminated by our hypervisors, so you do not need to send termination/delete signals given that will happen organically as a deployment stops receiving traffic.
Runtime APIs
End-users will be able to use regular Deno APIs and deno libraries in their new edge deployments.
Allowing for seamless local development using the deno
CLI (potentially
spawned via your own CLI)
Permissions & Limits
Isolates have 50ms CPU time per request, they can make outbound HTTP requests & open TCP/TLS connections (e.g: for databases). However Deploy will guard against circular calls to Deploy hosted apps.
x-deno-subhost example
A JWT signed with the shared secret:
header: { "kid": "acme_corp", "alg": "HS256", "typ": "JWT" }
claims: { "deployment_id": #opaque_id, exp, iat, rpc_root? }
x-forwarded-host
x-forwarded-host: foo.example.com