Deploy Ramose
Ramose deploys as a Cloudflare data plane declared in the same TypeScript stack as your application. Use separate Alchemy stages for development, preview, and production.
Declare the resource
Section titled “Declare the resource”import * as Alchemy from "alchemy"import * as Cloudflare from "alchemy/Cloudflare"import * as Effect from "effect/Effect"import * as Layer from "effect/Layer"import * as Ramose from "ramose"import { auth } from "./src/auth.ts"
const Store = Cloudflare.R2.Bucket("TasksStore", { name: "ramose-tasks-store",})
const Server = Ramose.Server("Tasks", { main: import.meta.resolve("./peer.ts"), storage: Store, auth,})
export default Alchemy.Stack( "ramose-tasks", { providers: Layer.mergeAll(Cloudflare.providers(), Ramose.providers()), state: Alchemy.localState(), }, Effect.gen(function* () { yield* Server }),)Ramose.Server provisions the public Worker, Durable Objects, object storage, synchronization, and MCP route. The Worker entry installs the application definition:
import * as Effect from "effect/Effect"import { QueryReplicaDO, createServer, createTransactorDO, deployOperationCatalogs,} from "ramose/worker"import { deployment } from "./src/domain.ts"
const operationCatalogs = await Effect.runPromise( deployOperationCatalogs(deployment),)
export default createServer({ operationCatalogs })export { QueryReplicaDO }export const TransactorDO = createTransactorDO(operationCatalogs)The domain module exports deployment with the named schema as root and an explicit database deployment. Keep that module shared with the web application so both ends use the same definition identities.
Run a local stage
Section titled “Run a local stage”bun alchemy devLocal development uses the real Worker, Durable Object, object-storage, cache, WebSocket, and auth topology through Alchemy’s local runtime. Give test data unique database names instead of replacing infrastructure with in-process substitutes.
Use a non-production stage and explicit local identity configuration. Test instrumentation activates only when its flag and non-production stage guard are both present.
Deploy a preview
Section titled “Deploy a preview”bun alchemy deploy --stage previewA stage is an isolated copy of compute, storage, catalogs, and secrets. Do not point a preview application at production database storage. Set the identity provider’s issuer, audience, keys, callback URLs, and allowed origins for the exact stage URL.
Deploy production
Section titled “Deploy production”bun alchemy deploy --stage prodCatalog validation runs before incompatible definitions can reinterpret stored data. Prefer additive releases: deploy readers that tolerate both shapes, backfill, switch writers, then remove the old shape in a later release.
Production requires authentication and policy. The data plane is fail-closed when they are absent or invalid; do not add an unauthenticated fallback to make a health check pass.
Verify the public surface
Section titled “Verify the public surface”Check liveness without relying on application data:
curl https://data.example.com/healthThen verify with real principals:
- An unauthenticated
/db/*and/mcprequest is denied. - A member can open only its authorized root and child paths.
- A viewer’s query cannot infer filtered fields through relationships or counts.
- One permitted operation commits and appears in the browser replica.
- One forbidden operation produces a rejected receipt without revealing a hidden target.
- MCP discovery returns
describe,query, andmutate, then an MCP mutation converges in the web app.
Treat teardown as data deletion
Section titled “Treat teardown as data deletion”Destroying a stage removes the resources Alchemy owns and may delete its database storage. Export or preserve anything you need before teardown, confirm the exact stage name, and never use a broad production stage as a local scratch environment.