Railway

Deploy temporal-cluster

Open Source Durable Workflow Engine. Retries, schedules & timers

Deploy temporal-cluster

Just deployed

Just deployed

Just deployed

Just deployed

/var/lib/postgresql/data

Just deployed

Just deployed

Temporal logo

Deploy and Host Temporal on Railway

Temporal is a durable execution engine for code that has to finish. You write an ordinary function — charge a card, provision an account, run a reconciliation — and Temporal records every step, so a crashed process, a redeploy or a third-party API that is down for an hour does not lose the work. Execution resumes from the last completed step. Stripe, Netflix and Datadog run it in production.

This template runs a full multi-service Temporal cluster, not a single-container development server. The four server roles — frontend, history, matching and worker — each get their own Railway service, the topology Temporal's own Helm chart deploys, so a busy role scales without touching the others. Managed Postgres holds both the execution history and the visibility index, so no Elasticsearch is required, and the Web UI runs privately behind a Caddy gateway terminating HTTP basic authentication. Self-host Temporal on Railway and you get the production shape on the first deploy.

Temporal server roles, web UI and Postgres on Railway

Getting Started with Temporal on Railway

Deploy the template, pick a username and password for the Web UI, and wait for the seven services to go green. First boot runs longer: the frontend creates Temporal's database role, applies both schemas and registers the default namespace while the other roles wait.

Open the public URL and enter the credentials you chose at deploy time — there is no account to create inside Temporal, since the Web UI has no user database. You land on an empty workflow list for default.

Click Start Workflow to confirm the cluster works end to end: any workflow ID, a task queue such as orders, a type such as ProcessOrderWorkflow. The execution appears as Running with a run ID, and opening it shows the event history and timeline — one click exercising the frontend, the history service and the visibility index.

It stays Running with a "no workers polling" banner, which is correct: Temporal orchestrates, and the code executing your steps is a worker you write. Deploy it as another service here and point the SDK client at temporal-frontend.railway.internal:7233. SDKs exist for Go, Java, TypeScript, Python and .NET.

Temporal Web UI listing two running workflow executions Temporal workflow detail with run ID and execution timeline Temporal namespace settings showing retention and search attributes

About Hosting Temporal

Temporal separates what your business logic does from when and whether it succeeds. Your workflow code runs on your own workers; the cluster stores every event, retries failed steps on a policy you configure, keeps timers that survive restarts, and guarantees a started workflow reaches a terminal state — which is what teams want when cron jobs and queue consumers stop being enough.

Key features:

  • Durable state — per-workflow event history, so a restart replays instead of restarting
  • Automatic retries and timeouts as activity-level policy, not hand-written loops
  • Long-running workflows — timers measured in days or months, not held in memory
  • Signals, queries, updates and schedules, replacing cron for recurring work
  • A Web UI for searching executions and terminating runs

One service per responsibility: temporal-frontend is the API gateway clients and workers connect to; temporal-history owns the shards and event history; temporal-matching hosts the task queues that hand work to workers; temporal-worker runs Temporal's own system workflows; Postgres stores the temporal and temporal_visibility databases; temporal-ui serves the dashboard; proxy holds the only public domain.

Why Deploy Temporal on Railway

Railway removes the operational work that usually makes a Temporal cluster a project of its own.

  • Four server roles, Postgres and the UI in one click
  • Private networking between roles, so only the gateway is exposed
  • Schema and namespace set up automatically on first boot
  • Managed Postgres instead of a database you babysit
  • Scale any single role independently as load changes

Common Use Cases

  • Order and payment flows where a failure between "charged" and "shipped" must never be lost
  • Account provisioning spanning third-party APIs, each with its own retry and rollback behaviour
  • Long-running AI and data jobs — agent runs, ETL, batch enrichment — needing checkpoints
  • Scheduled business processes such as billing and reconciliation, replacing cron

Dependencies for Temporal

  • temporalio/server:1.31 — the server binary, run four times with a different role each
  • temporalio/admin-tools:1.31 — schema tool, DDL and the temporal CLI, used at first boot
  • temporalio/ui:latest — the Web UI (temporalio/ui)
  • caddy:2-alpine — basic-authentication gateway in front of the Web UI
  • Railway managed Postgres 18 — persistence and visibility store

Environment Variables Reference

VariableServicePurpose
TEMPORAL_SERVICESserver rolesRole to run: frontend, history, matching, worker
NUM_HISTORY_SHARDSserver rolesShard count, fixed at first boot
DBNAME / VISIBILITY_DBNAMEserver rolesThe two Postgres database names
DEFAULT_NAMESPACE_RETENTIONfrontendClosed history retention
TEMPORAL_ADDRESSWeb UIThe frontend's private gRPC address
UI_USERNAME / UI_PASSWORDproxyCredentials for the public Web UI

Deployment Dependencies

Hardware Requirements for Self-Hosting Temporal

Per Temporal service, with Postgres sized separately.

ResourceMinimumRecommended
CPU0.5 vCPU per role1–2 vCPU per role
RAM512 MB per role1–2 GB, more for history
Storage5 GB Postgres volume20 GB+, sized by retention
RuntimePostgreSQL 12+PostgreSQL 18

History is the memory-hungry role, holding context for every shard it owns. Retention drives storage; closed histories are kept three days by default.

Self-Hosting Temporal

A single-container cluster for local development, via the Temporal CLI:

temporal server start-dev --ui-port 8080

The production shape, one container per role against external Postgres:

docker run -d --name temporal-history \
  -e TEMPORAL_SERVICES=history \
  -e DB=postgres12 \
  -e POSTGRES_SEEDS=postgres.internal \
  -e POSTGRES_USER=temporal \
  -e POSTGRES_PWD=your-password \
  -e DBNAME=temporal \
  -e VISIBILITY_DBNAME=temporal_visibility \
  -e NUM_HISTORY_SHARDS=512 \
  -e BIND_ON_IP=:: \
  temporalio/server:1.31

Both databases need their schema applied once first, from the admin-tools image:

temporal-sql-tool --plugin postgres12 --ep postgres.internal -u temporal -p 5432 \
  --db temporal setup-schema -v 0.0
temporal-sql-tool --plugin postgres12 --ep postgres.internal -u temporal -p 5432 \
  --db temporal update-schema -d /etc/temporal/schema/postgresql/v12/temporal/versioned

Is Temporal Free to Self-Host?

Temporal Server is open source under the MIT licence — no paid tiers, seat limits or feature gates, and the SDKs and Web UI are open source too. Temporal Cloud is the managed offering, billed per action and stored event; self-hosting replaces that bill with infrastructure. On Railway you pay only for the compute and storage the seven services use.

FAQ

What is Temporal? An open-source durable execution engine. It runs your workflow code as normal functions while persisting every step, so failures and restarts resume rather than lose work.

What does this Railway template deploy? A complete Temporal cluster: frontend, history, matching and worker as separate services, managed Postgres, the Web UI, and a Caddy gateway putting basic authentication in front of it.

Why does the template include Postgres? Temporal keeps no state on disk. Postgres holds every workflow's event history and, in a second database, the visibility index behind workflow search — Temporal supports Postgres for advanced visibility natively, so Elasticsearch is not needed.

How do I connect a worker to self-hosted Temporal on Railway? Deploy the worker as another service in the same Railway project and point the SDK client at temporal-frontend.railway.internal:7233. The frontend is intentionally private, so workers live in the project rather than on the internet.

Why is the Temporal frontend not exposed publicly? Its gRPC API ships without authentication, and securing it needs mTLS certificates or a JWT authorizer only you can supply. Keeping it private means anyone who finds the public URL reaches the password-protected Web UI, not the cluster API.

Why does my first workflow stay in Running? Nothing is executing it yet. Temporal dispatches tasks to workers you run; until one polls the task queue you named, the workflow waits. That is expected on a fresh cluster and confirms the server side is healthy. Note also that NUM_HISTORY_SHARDS is fixed when the cluster is created — this template ships Temporal's recommended 512.


Template Content

More templates in this category

View Template
N8N Main + Worker
Deploy and Host N8N with Inactive worker.

jakemerson
119
View Template
Evolution API with n8n
[Jul'26] WhatsApp automation platform using Evolution API, n8n & PostgreSQL

codestorm
77
View Template
Postgres Backup
Cron-based PostgreSQL backup to bucket storage

Railway Templates
870