---
title: "Deploy temporal-cluster"
description: "Open Source Durable Workflow Engine. Retries, schedules & timers"
category: "Automation"
url: https://railway.com/deploy/temporal-cluster
---

# Deploy temporal-cluster

Open Source Durable Workflow Engine. Retries, schedules & timers

**[Deploy temporal-cluster on Railway](https://railway.com/template/temporal-cluster)**

- **Creator:** A3A
- **Category:** Automation
- **Total deploys:** 2

## Template content

### temporal-worker https://cdn.simpleicons.org/temporal/FFFFFF

- **Source:** https://github.com/gridalpha/temporal-railway

### temporal-ui https://cdn.simpleicons.org/temporal/FFFFFF

- **Image:** temporalio/ui:latest
- **Health check:** /healthz

### proxy https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/caddy.svg

- **Source:** https://github.com/gridalpha/temporal-railway
- **Public domain:** Yes

### temporal-history https://cdn.simpleicons.org/temporal/FFFFFF

- **Source:** https://github.com/gridalpha/temporal-railway

### Postgres https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/postgresql.svg

- **Image:** ghcr.io/railwayapp-templates/postgres-ssl:18

### temporal-frontend https://cdn.simpleicons.org/temporal/FFFFFF

- **Source:** https://github.com/gridalpha/temporal-railway

### temporal-matching https://cdn.simpleicons.org/temporal/FFFFFF

- **Source:** https://github.com/gridalpha/temporal-railway

## Documentation

![Temporal logo](placeholder-logo.png)

# 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](https://res.cloudinary.com/rroe4rtk/image/upload/v1787131764/temporal-architecture.png)

## 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](https://res.cloudinary.com/rroe4rtk/image/upload/v1787121137/temporal-workflow-list.png)
![Temporal workflow detail with run ID and execution timeline](https://res.cloudinary.com/rroe4rtk/image/upload/v1787121143/temporal-workflow-history.png)
![Temporal namespace settings showing retention and search attributes](https://res.cloudinary.com/rroe4rtk/image/upload/v1787121148/temporal-namespace-detail.png)

## 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](https://github.com/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

| Variable | Service | Purpose |
|---|---|---|
| `TEMPORAL_SERVICES` | server roles | Role to run: `frontend`, `history`, `matching`, `worker` |
| `NUM_HISTORY_SHARDS` | server roles | Shard count, fixed at first boot |
| `DBNAME` / `VISIBILITY_DBNAME` | server roles | The two Postgres database names |
| `DEFAULT_NAMESPACE_RETENTION` | frontend | Closed history retention |
| `TEMPORAL_ADDRESS` | Web UI | The frontend's private gRPC address |
| `UI_USERNAME` / `UI_PASSWORD` | proxy | Credentials for the public Web UI |

### Deployment Dependencies

- Source: [temporalio/temporal](https://github.com/temporalio/temporal) (MIT)
- Docker Hub: `temporalio/server`, `temporalio/admin-tools`, `temporalio/ui`
- Docs: [docs.temporal.io](https://docs.temporal.io/) — self-hosting guide, SDKs, samples

## Hardware Requirements for Self-Hosting Temporal

Per Temporal service, with Postgres sized separately.

| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 0.5 vCPU per role | 1–2 vCPU per role |
| RAM | 512 MB per role | 1–2 GB, more for history |
| Storage | 5 GB Postgres volume | 20 GB+, sized by retention |
| Runtime | PostgreSQL 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.


## Similar templates

- [N8N Main + Worker](https://railway.com/deploy/n8n-main-worker) — Deploy and Host N8N with Inactive worker.
- [Evolution API with n8n](https://railway.com/deploy/evolution-api-with-n8n) — Automate WhatsApp workflows with Evolution API, n8n, and Postgres.
- [Postgres Backup](https://railway.com/deploy/postgres-s3-backups) — Cron-based PostgreSQL backup to bucket storage

Open this page in a browser: https://railway.com/deploy/temporal-cluster
