Railway

Deploy Apache Kafka | Open Source Event Streaming (KRaft, no ZooKeeper)

Kafka in KRaft mode with a web console — no ZooKeeper, data on a volume

Deploy Apache Kafka | Open Source Event Streaming (KRaft, no ZooKeeper)

Just deployed

Just deployed

/var/lib/kafka/data

Deploy and Host Apache Kafka on Railway

Apache Kafka is the distributed log that most event-driven systems are built on: producers append records to topics, consumers read them at their own pace, and nothing is lost in between. This template runs it in KRaft mode — no ZooKeeper — with a web console in front of it.

About Hosting Apache Kafka

This template runs the official apache/kafka image on a pinned stable tag, with partitions and the metadata log on a persistent Railway volume, plus kafbat's Kafka UI as a management console. Nothing is rebuilt or forked, so upstream releases and upstream security fixes are what you get.

Two choices here are worth stating plainly, because they are the ones that go wrong elsewhere.

The image is Apache's own, not Bitnami's. Bitnami removed versioned tags from the free Docker Hub tier in 2025, and templates pinned to them stopped deploying — a template that cannot pull its image is worse than no template.

The broker is reachable only inside your Railway project, at kafka.railway.internal:9092. Kafka has no authentication over PLAINTEXT, so a broker on a public TCP proxy is a cluster anyone can produce to, consume from and delete topics in. Doing external access properly means SASL, certificates and a client configuration this template cannot fill in for you. The console is the one thing on a public domain, and it sits behind a login form with a generated password.

Common Use Cases

  • Decoupling services: Let services publish events instead of calling each other, so a slow or restarting consumer never takes the producer down with it.
  • Durable job and event queues: Retain a replayable log rather than a queue that forgets — reprocess from any offset after a bug fix.
  • Streaming pipelines and CDC: Feed change data, clickstreams or telemetry into analytics, search or a warehouse, with backpressure handled by the log itself.

Dependencies for Apache Kafka Hosting

Deployment Dependencies

  • Apache Kafka 4.3 in KRaft mode — no ZooKeeper
  • Kafbat Kafka UI 1.5 — topic browser, message viewer, consumer group inspector
  • A Railway volume mounted at /var/lib/kafka/data
  • Producers and consumers running in the same Railway project

Implementation Details

RAILWAY_RUN_UID=0 runs the broker as root. The apache/kafka image declares USER appuser, and a non-root process cannot take ownership of a freshly attached Railway volume — without this the broker starts and immediately fails to write its log directory. This is Railway's documented answer for images that run as a fixed non-root user and need a volume.

KAFKA_LOG_DIRS points at /var/lib/kafka/data/logs, one level below the mount point rather than at it. Railway creates a lost+found entry at the root of every volume, and Kafka treats every entry inside a log directory as a partition directory, so pointing it at the mount root aborts the boot with Found directory /var/lib/kafka/data/lost+found, 'lost+found' is not in the form of topic-partition. The image's own default, /tmp/kraft-combined-logs, is worse in a quieter way: it is the ephemeral container layer, so every topic would vanish on the next deploy without an error anywhere.

KAFKA_LISTENERS leaves the host empty — PLAINTEXT://:9092. The JVM binds a dual-stack wildcard socket that way, which is what Railway's IPv6-only private network requires. Writing 0.0.0.0 instead makes kafka.railway.internal unreachable to every other service in the project.

KAFKA_ADVERTISED_LISTENERS uses ${{RAILWAY_PRIVATE_DOMAIN}}. Bootstrap returns the advertised address, and clients reconnect to that, not to the host they dialled. Left at the default, the broker advertises its container hostname: the first connection succeeds and every subsequent one times out — a failure that looks like a network problem and is not.

CLUSTER_ID is generated once and written into the volume on the first boot. The image's entrypoint exits immediately if it is unset, and changing it later describes a cluster that is not the one on disk. Every replication factor is pinned to 1 because there is one broker; left at multi-broker defaults, the internal offsets topic is never created and the first consumer group hangs forever.

The broker carries no healthcheck, deliberately. Railway keeps the previous container serving until a new one reports healthy, while Kafka holds an exclusive lock on its log directory — with both on the same volume that is a deadlock, and every redeploy after the first would fail. The console does have one, at /actuator/health, because it is stateless.

Why Deploy Apache Kafka on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Apache Kafka on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

Resources: 1 GB RAM for the broker and around 512 MB for the console is a comfortable start, with a 1 GB volume that can be grown later without downtime. The heap is capped at 512 MB — raise KAFKA_HEAP_OPTS and the service memory together, not one without the other. Retention is the default seven days; disk is what runs out first on a busy topic, so set retention.ms per topic before you scale the volume.


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