Skip to main content
Reference

Architecture

How Dynamic Apps serves, builds, and stores user-generated applications.

Dynamic Apps is a library, not a hosted app deployment platform. You own the routing server, its authentication, and the URL on which applications are mounted.

Request Agent · Browser · API Your Node.js server Middleware Dynamic Apps router agentOS VM

The request lifecycle looks like:

  1. Your routing server receives a request.
  2. Your middleware handles it: authentication, rate limits, whatever else you run.
  3. The request is passed to appsRouter.
  4. appsRouter executes it in the agentOS VM for that app, starting the VM if it isn’t already running.
import { serve } from "@hono/node-server";
import { appsRouter } from "@rivet-dev/dynamic-apps";
import { Hono } from "hono";

const server = new Hono();

// This is how the Rivet control plane communicates with your backend.
server.all("/api/rivet/*", (c) => appsRouter.fetch(c.req.raw));

// Mount every deployed application at /apps/:appId.
server.route("/apps", appsRouter);

// Serve the host router over HTTP.
serve({
	fetch: server.fetch,
	port: 3000,
});

Requests reach your routing server, where appsRouter executes them in a cached agentOS VM embedded in the same process. There is no network hop to another service, and warm requests never touch storage. Apps export fetch handlers; Dynamic Apps owns any listener inside the VM.

Deployment is separate from serving

deployApp() builds the files in a sandboxed agentOS build VM and publishes an immutable release. The default @rivet-dev/dynamic-apps package stores releases in Rivet. @rivet-dev/dynamic-apps-core lets you supply another store.

App-defined actors

An app may also export a RivetKit registry. Those app-defined actors use normal Rivet routing for durable state, actions, events, and connections. Dynamic Apps imports the app once into a cached server process, then sends both ordinary HTTP and Rivet callbacks through that process.

agentOS provides the filesystem, process, environment, and network permission boundary for direct requests and app-defined actor workers.