Skip to content

Bucket

Source: src/Railway/Bucket.ts

A Railway.Bucket is S3-compatible object storage in a Project. Each environment gets its own isolated instance and credentials. Bind PutObject / GetObject (and the other S3 object ops) in Service init — Alchemy injects the endpoint and credentials.

Railway has no labels. Ownership is stamped into the display name via createPhysicalName. name updates in place. Changing project, environment, or region replaces the Bucket.

Pass a Project. Alchemy generates a unique name and deploys to the project’s primary environment in sjc.

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

Pass name when you need a stable display name. The S3 API name is this plus a short hash (s3BucketName).

const data = yield* Railway.Bucket("Data", {
project: site,
name: "uploads",
});

Omit region to use sjc. Changing it replaces the Bucket.

const data = yield* Railway.Bucket("Data", {
project: site,
region: "iad",
});

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

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

Railway buckets speak the S3 API. Bind PutObject / GetObject in Service init.

import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
export default class Api extends Railway.Service<Api>()(
"Api",
{ project: Site, main: import.meta.url },
Effect.gen(function* () {
const putObject = yield* Railway.PutObject(Data);
const getObject = yield* Railway.GetObject(Data);
return {
fetch: Effect.gen(function* () {
yield* putObject({
Key: "hello.txt",
Body: "hello",
ContentType: "text/plain",
});
const obj = yield* getObject({ Key: "hello.txt" });
return HttpServerResponse.json({ ok: obj.ETag !== undefined });
}),
};
}).pipe(Effect.provide([Railway.PutObjectHttp, Railway.GetObjectHttp])),
) {}

Declare the Project once. Pass it into every child. Resource-valued props accept the resource or an Effect producing it.

src/data.ts
import * as Railway from "alchemy/Railway";
export const Site = Railway.Project("Site");
export const Data = Railway.Bucket("Data", { project: Site });