What is Railway?
Railway runs containers for you. You put services in a project: your API, a worker, a Postgres database, a Redis cache. Railway builds each one, runs it, gives it a URL, and connects the services in a project over a private network. You pay for the CPU and memory they actually use.
Take one small app: an API service with a Postgres database and a Volume, in one project. A workspace holds the project. The project runs a full copy of its services in each environment, and services in one environment reach each other over its private network.
Workspaces and tokens
Section titled “Workspaces and tokens”A workspace is your account or your team on Railway. It holds your projects and their bill. Alchemy creates projects in your token’s workspace, or, for an account token or OAuth, in your first workspace. A Project can name another with workspaceId.
Connect a token once, in Setup.
Projects
Section titled “Projects”A project groups the services that make up one app, with their databases, volumes and variables. Alchemy generates a unique name for it unless you give one, so each stage gets its own project.
export const Site = Railway.Project("Site");See Projects.
Environments
Section titled “Environments”Every project has a production environment, created with it. An environment is a full copy of the project’s services, with its own variables and its own data, so a staging environment can run the same app against its own database.
See Environments.
Services: a container each
Section titled “Services: a container each”A service is one container in a project. It runs a public image, code from a GitHub repository, or, in Alchemy, your Effect program, which Alchemy bundles and Railway builds into an image:
export default class Api extends Railway.Service<Api>()( "Api", { project: Site, main: import.meta.url, port: 3000 }, Effect.gen(function* () { return { fetch: Effect.succeed(HttpServerResponse.text("hello from Railway")), }; }),) {}Each build of a service is a deployment. Railway starts the new one, waits for its health check, and then moves traffic to it.
See Services.
Functions
Section titled “Functions”A function is a service made from one TypeScript file, with no Dockerfile and no image registry. It can answer HTTP or run on a cron schedule.
See Functions, templates & VMs.
Regions
Section titled “Regions”A service, volume or database runs in one region, like us-west2. Running it near its users, or near its database, cuts latency.
See Regions.
Databases
Section titled “Databases”Railway runs databases as services, from official images: Postgres, MySQL, Mongo and Redis. Each keeps its data on a volume and publishes a connection URL as a variable. A service reaches it through a binding that hands it the connection string.
See Postgres, MySQL, Mongo and Redis.
Volumes and buckets
Section titled “Volumes and buckets”A volume is a disk mounted into one service, whose files survive deploys and restarts. A bucket is object storage that speaks the S3 API, for files any service can read and write.
Variables
Section titled “Variables”Variables are environment variables for a service, set per environment. A variable can refer to another service’s, so the API’s DATABASE_URL follows the database’s. Values from your .env read with effect/Config reach a service the same way.
See Variables.
Networking: domains, TCP and the private network
Section titled “Networking: domains, TCP and the private network”A service with a port gets a public *.up.railway.app domain, and can take a custom domain of yours. A TCP proxy exposes a database to the internet, for a migration or a tool on your laptop. Inside a project, services reach each other at {service}.railway.internal over a private network, never leaving Railway.
See Custom domains, TCP & private networks.
State: where Alchemy keeps its record
Section titled “State: where Alchemy keeps its record”Railway has no storage for Alchemy’s own record of what each Stack created. Keep it on disk with Alchemy.localState(), or share it with your team and CI through Cloudflare.state() or AWS.state().
export default Alchemy.Stack( "MyApp", { providers: Railway.providers(), state: Alchemy.localState() }, Effect.gen(function* () { const api = yield* Api; return { url: api.url }; }),);How @alchemy.run/railway models these concepts
Section titled “How @alchemy.run/railway models these concepts”Each of these concepts is something your Stack declares.
Your API token picks the workspace, and Railway.providers() deploys into it. A project and its environments are declarations. A service is your program, an image or a repository, running in the project. Databases, volumes, buckets, variables and domains are declarations like any other, and bindings hand a service the connection details for what it uses.
Next, build one: the tutorial puts these ideas to work, one step at a time. Or read the concepts in depth, starting with Projects.