Skip to content

Volumes

A Railway.Volume is block disk in a Project. Create it disconnected (no service) and attach later with MountVolume, or pass service to attach at create time.

The disk outlives deploys. mountPath updates in place. Changing project, environment, or region replaces the Volume.

Pass a Project and a mount path. Alchemy generates a unique name. The volume is disconnected until you attach a Service.

const site = yield* Railway.Project("Site");
const data = yield* Railway.Volume("Data", {
project: site,
mountPath: "/data",
});

Inside a Service’s init, bind the Volume to a path and use it as a plain directory at runtime:

export default class Api extends Railway.Service<Api>()(
"Api",
{ project: Site, main: import.meta.url, port: 3000 },
Effect.gen(function* () {
const disk = yield* Railway.MountVolume(Data, { path: "/data" });
const fs = yield* FileSystem.FileSystem;
return {
fetch: Effect.gen(function* () {
const text = yield* fs.readFileString(`${disk.path}/hello.txt`);
// ...
}),
};
}).pipe(Effect.provide(Railway.MountVolumeLive)),
) {}

At deploy time the binding writes { path, volumeId } into the Service. Reconcile attaches the volume via volumeInstanceUpdate. At runtime you get disk.path.

Railway allows one volume per Service. It does not give each replica its own disk. A second volume on the same Service is Railway.MultipleVolumes.

Pass service to attach when the Volume is created:

const api = yield* Railway.Service("Api", {
project: site,
image: "hashicorp/http-echo",
port: 5678,
});
const data = yield* Railway.Volume("Data", {
project: site,
mountPath: "/data",
service: api,
});

Updating service attaches or moves the volume in place. The target Service must not already have a volume.

Defaults to the Project’s primary environment. Pass a Environment (or { environmentId }) to target another one.

const staging = yield* Railway.Environment("Staging", { project: site });
const data = yield* Railway.Volume("StagingData", {
project: site,
environment: staging,
mountPath: "/data",
});

Omit region to use Railway’s default. Changing it replaces the Volume. See Regions.

const data = yield* Railway.Volume("Data", {
project: site,
mountPath: "/data",
region: "us-west2",
});

Railway.VolumeBackup is a snapshot of a volume instance. The volume should be attached to a Service — Railway only backups mounted volumes. lock drops the expiration. schedules (DAILY / WEEKLY / MONTHLY) is volume-instance state.

const snap = yield* Railway.VolumeBackup("Nightly", {
volume: data,
lock: true,
schedules: ["DAILY", "WEEKLY"],
});

Restore is destructive to the volume instance. Call restoreVolumeBackup — it is not a reconciler step. Volume backups are Pro-plan gated (RailwayForbidden on Hobby).