Railway

Deploy Temporal | Durable Workflows, No Elasticsearch

Durable workflows on Postgres alone - 650 MiB less than the ES version

Deploy Temporal | Durable Workflows, No Elasticsearch

Just deployed

Just deployed

/var/lib/postgresql/data

Just deployed

Just deployed

Deploy and Host Temporal on Railway

Temporal is a durable execution platform: you write ordinary code, and Temporal makes it survive crashes, restarts and deploys. Workflows keep their state, retries are automatic, and long-running processes can span days or months without you building a job table and a cron to babysit it.

About Hosting Temporal

Most self-hosted Temporal setups run Elasticsearch next to Postgres, because that is what the official docker-compose files do. Elasticsearch is there for one feature: advanced visibility — custom search attributes and filtered workflow queries such as OrderTier="gold".

Since Temporal 1.20 that feature works on PostgreSQL 12+ directly. Elasticsearch is no longer required for it, but the popular Railway templates still ship it, and it is by far the largest thing in the project.

This template drops Elasticsearch and keeps the feature. Measured on Railway on 2026-08-15, both stacks idling in the same environment on the same plan:

this templatethe most-deployed Temporal template
Postgres239 MiB154 MiB
Temporal668 MiB75 MiB
Elasticsearch1305 MiB
UI (+ auth proxy)9 MiB31 MiB
Total915 MiB1565 MiB

650 MiB less, about 42%, and the Elasticsearch container alone is larger than this entire stack. Two things to be straight about: the other template's Temporal container was still warming up when it was sampled, so the real gap is a little smaller than the table suggests; and this template's Temporal runs heavier on purpose (see history shards below).

Verified on the running deploy, not assumed:

  • operator cluster health reports SERVING
  • a custom search attribute (OrderTier, Keyword) was created against Postgres
  • two workflows were started and workflow list --query 'OrderTier="gold"' returned exactly one

Why Deploy Temporal on Railway?

Railway runs all four pieces — server, database, UI and the TCP proxy your workers dial — as one project with private networking already wired, so there is no compose file, no VPC and no TLS plumbing to write. Because this template leaves Elasticsearch out, it fits comfortably on the small plans where a 1.5 GB stack would not, and the bill tracks a Postgres rather than a JVM search cluster you were only using to filter a list.

Common Use Cases

  • Background jobs that must not be lost when a container restarts mid-run
  • Multi-step order, payment, onboarding or provisioning flows with automatic retries
  • Long-running processes measured in hours, days or months (trials, dunning, scheduled reminders)
  • Orchestrating calls across several services or third-party APIs, with each step made durable
  • Replacing a hand-rolled jobs table, cron and retry loop with something that keeps its own state

Dependencies for Temporal Hosting

  • PostgreSQL 12 or newer — included in this template, with a volume. Holds both the main and the visibility database.
  • A Railway TCP proxy on the Temporal service — included, and how workers outside Railway reach gRPC on port 7233.
  • Nothing else. There is deliberately no Elasticsearch, and no external message broker or cache.

Deployment Dependencies

What you get

  • Temporal server (temporalio/auto-setup, pinned) — schema setup and the default namespace are created on first boot, so there is no manual temporal-sql-tool step.
  • PostgreSQL with a volume, holding both the main and the visibility database.
  • Temporal Web UI, private, reachable only through the auth proxy below.
  • Basic-auth proxy on the public HTTPS URL, with a generated 32-character password. The UI is never exposed unauthenticated — anyone who finds the URL without credentials gets a 401, and the Web UI can terminate workflows, so this is not optional.
  • gRPC on a Railway TCP proxy, so real workers outside Railway can connect.

Settings chosen for you, and why

  • NUM_HISTORY_SHARDS=512. This value cannot be changed after the cluster is created — changing it means starting over and losing your workflow history. Temporal's own default in the container image is 4, which is fine for a demo and a wall you hit later. 512 is Temporal's production recommendation. It costs some memory now and saves a migration you cannot do.
  • BIND_ON_IP=::. Railway's private network is IPv6-only; binding IPv4 leaves the UI unable to reach the server, and because Temporal has no HTTP healthcheck the deploy still goes green while the cluster is dead.
  • Retention 72h on the default namespace, so a busy queue does not quietly grow the database forever. Raise it per namespace when you know what you need.

Connecting a worker

Your workers connect over the TCP proxy, not the web URL:

temporal --address : operator cluster health

Both values are on the Temporal service's Variables tab. In an SDK, that host:port is the Client target address, and the namespace is default.

Custom search attributes

temporal --address  operator search-attribute create --name OrderTier --type Keyword
temporal --address  workflow list --query 'OrderTier="gold"'

No Elasticsearch involved — these are columns in Postgres.

When you should use the Elasticsearch version instead

Honest limits. SQL visibility is the right default, not the right answer for everyone:

  • Very high workflow volume. Elasticsearch scales visibility queries past what a single Postgres will comfortably serve.
  • Full-text search over Text search attributes with real relevance ranking.
  • An existing Elasticsearch you already run and want Temporal to index into.

For the great majority of Railway deploys — internal tooling, background jobs, order and onboarding flows — Postgres visibility is enough, and the 1.3 GB is pure cost.


Template Content

More templates in this category

View Template
smoothmq
A drop-in replacement for AWS SQS

poundifdef
7
View Template
Kafka UI
Kafbat UI — Open-source web UI to monitor and manage Apache Kafka clusters

codestorm
0
View Template
Hatchet Lite
Hatchet Lite with postgres

prncd
1