Skip to main content
Advanced

Core

Use Dynamic Apps Core to own release storage, loading, and invalidation.

Use @rivet-dev/dynamic-apps-core when your host owns release persistence and notifications:

import { createDynamicApps } from "@rivet-dev/dynamic-apps-core";

const dynamicApps = createDynamicApps({
  async publishRelease(input) {
    // Persist input.artifact.bytes, then atomically make this release active.
    await store.putArtifact(input.buildId, input.artifact.bytes);
    await store.activate(input.appId, input.buildId, input);
    return { appId: input.appId, release: input.buildId };
  },
  async loadActiveRelease(appId) {
    // Return one coherent metadata + complete-artifact snapshot.
    return store.loadActive(appId);
  },
  async watchActiveRelease(appId, invalidate) {
    // Resolve only after the subscription is live.
    return store.subscribe(appId, invalidate);
  },
});

Hook guarantees

  • Publish a release: make the verified artifact durable before atomically activating it. Do not resolve until a load can observe the new release. A failed publish must leave the previous release active.
  • Load the active release: return coherent metadata and complete bytes in one logical operation. Core copies and independently verifies the bytes.
  • Watch for updates: subscribe before resolving, invalidate after every activation, and invalidate after a disconnect that may have missed events. Duplicate invalidations are safe.

The watcher is required. A no-op watcher is safe only when an app ID cannot change for the entire lifetime of every serving process.

Call await dynamicApps.dispose() during shutdown to release subscriptions, build resources, cached runtimes, and agentOS contexts.

Deployed app entrypoints only export a Fetch handler; they never bind a port. If Core loads an actor-enabled release, provide its server.environment and a shared serverRuntime. The standard @rivet-dev/dynamic-apps package supplies that actor runtime automatically.

Get started with the Quickstart (Core).