The Rivet JavaScript runtime is built on lightweight JavaScript containers called V8 isolates, providing a high-performance, secure environment for your actor code.
It's designed to be widely compatible with Node.js and NPM dependencies, making it easy to use familiar libraries and tools.
This guide is for advanced usage of Rivet
For getting started quickly, we recommend using ActorCore.
Add the @rivet-gg/actor package to your project for comprehensive TypeScript definitions:
Command Line
npm install -S @rivet-gg/actor
This package is optional
You can use Rivet actors without this package, but you'll need to define your own types.
Every actor must export a default object with an async start function. Here's a simple HTTP server example:
src/index.ts
import type { ActorContext } from "@rivet-gg/actor";import * as http from "http";export default { async start(ctx: ActorContext) { // Get the port from environment variables or use a default const port = parseInt(process.env.PORT_HTTP || "8080"); console.log(`HTTP server running on port ${port}`); // Create an HTTP server const server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end(`Hello from Rivet Actor ${ctx.metadata.actor.id} running in ${ctx.metadata.region.id}!`); }); // Start listening on the specified port server.listen(port); // Keep the actor running until explicitly destroyed await new Promise((resolve) => {}); }};
What this code does:
Sets up a simple HTTP server using Node.js's built-in http module
Creates a response that includes the actor ID and region information
Keeps the actor running indefinitely by returning a promise that never resolves
Using classes
You can also use a class with a static method for your entrypoint:
src/index.ts
import type { ActorContext } from "@rivet-gg/actor";export default class MyActor { static async start(ctx: ActorContext) { // Your HTTP server implementation would go here }}
In this step, you're requesting Rivet to launch your actor code in the cloud:
TypeScript
import { RivetClient } from "@rivet-gg/api";// Initialize the Rivet client with your API token// You can get this from the Rivet dashboardconst client = new RivetClient({ token: process.env.RIVET_TOKEN});// Create an actor - this launches your code on Rivet's infrastructureconst { actor } = await client.actors.create({ // Your project and environment IDs from the Rivet dashboard project: "your-project-id", environment: "your-environment-id", body: { // Tags help identify this specific actor instance // You can query actors by these tags later tags: { name: "my-actor" }, // buildTags determine which actor code to run // This should match tags in your rivet.json build configuration // The current tag is automatically assigned on deploy buildTags: { name: "my-actor", current: "true" }, // Network configuration for your actor network: { ports: { http: { // The protocol used for communication protocol: "https", } } }, // Optional: Specify a region for lower latency to specific users // If not specified, Rivet will choose the optimal region // region: "atl", }});// The actor.id is a unique identifier for this actor instanceconsole.log("Created actor:", actor.id);
What happens during creation:
Rivet finds the latest build matching your buildTags
It provisions resources in the specified region (or chooses the best one)
It starts your actor code with the provided environment variables
The actor starts running and initializes based on your code's start function
Once your actor is running, you can access its URL directly from the actor object:
TypeScript
// The actor response includes the URL information// You can access it for any port you configuredconst httpUrl = actor.network.ports.http.url;// The URL is a public endpoint to your actorconsole.log("Actor HTTP URL:", httpUrl);// Use the URL to communicate with your actor// In this example, we're calling the /hello endpoint on our HTTP serverconst response = await fetch(`${httpUrl}/hello`);const text = await response.text();console.log("Response from actor:", text);
What happens during connection:
Each port configured for your actor gets a unique URL
These URLs are accessible based on your actor's security settings
The URL routes to your actor regardless of which region it's in
For additional security, you can use getConnection to generate temporary, authenticated URLs
When you're finished using the actor, it's important to destroy it to free up resources:
TypeScript
// Destroy the actor to free up resources and stop billingawait client.actors.destroy(actor.id, { project: "your-project-id", environment: "your-environment-id",});console.log("Actor destroyed");
What happens during destruction:
Rivet sends a termination signal to your actor
Your actor gets a short grace period to clean up resources
All compute resources associated with the actor are freed
Always destroy actors when you're done with them to avoid unnecessary costs.
Actors will continue running and billing will continue until explicitly destroyed.