all posts

The best Kafka hosting platforms in 2026

Ajay Kumar··9 min read

Kafka is a distributed, partitioned, replicated commit log that has convinced a generation of teams they have a streaming problem. Sometimes they do. The teams that genuinely do get enormous value from it — a durable, replayable, ordered log is a load-bearing primitive you cannot easily fake. The teams that don't end up paying a five-figure annual bill and a permanent slice of somebody's on-call attention so that a nightly batch job can be described as an event pipeline.

I'm Ajay, I build PandaStack. I'll get the conflict of interest out of the way immediately: we do not host Kafka brokers and have no plans to. We host the applications — the producers, the consumers, the stream processors — that talk to somebody else's brokers, plus the managed Postgres those consumers usually write into. So I have no dog in the broker fight, which makes this a better guide than one written by a vendor and a worse one if you wanted somebody to sell you something.

What you are actually buying

Every managed Kafka page says 'fully managed, elastic, enterprise-grade'. Useless. Underneath the marketing, a Kafka service is really three separable things, and providers differ enormously in which of the three they actually take off your hands.

1. Brokers — the compute

Kafka brokers are stateful JVM processes that own partitions. Their cost driver is throughput and connection count, and their operational pain is rebalancing: adding or removing a broker means moving partition replicas across the network while the cluster is serving traffic. Some services hide this behind an autoscaler; others hand you a slider and a support ticket. This is the single largest difference between 'managed' and 'hosted' in this market.

2. Storage — the log

Retention is the knob nobody thinks about at design time and everybody thinks about at invoice time. Seven days of retention on a topic doing meaningful volume, replicated three ways, is a lot of provisioned disk sitting there being paid for continuously. Tiered storage — where old segments migrate to object storage and only recent segments live on broker disk — is the feature that turns this from a hard ceiling into a gentle slope. Check whether your provider offers it, on which tier, and whether reading from the tiered portion is billed separately.

3. The operational burden — the part you're really paying for

Partition rebalancing, consumer group lag alerting, rolling version upgrades, ACL management, schema compatibility enforcement, quota enforcement per client. A cheap Kafka that leaves all of this with you is not cheap; it's a Kafka-shaped bill plus a Kafka-shaped headcount. When you compare providers, price the difference in engineer-days, not in dollars per GB.

A rule of thumb that has held up well: if nobody on the team can currently explain what a consumer group rebalance is and when it triggers, self-hosting Kafka will cost you more than the most expensive managed option.

The KRaft era: one less thing to run

For most of Kafka's life, running it meant running two clusters: Kafka itself, plus a ZooKeeper ensemble holding cluster metadata. ZooKeeper was a real operational tax — a second quorum system with its own failure modes, its own upgrade path and its own way of ruining a Tuesday.

KRaft (Kafka Raft) moved metadata into Kafka itself, run by a quorum of controller nodes using Raft. ZooKeeper support was deprecated in Kafka 3.5 and removed in the 4.x line, so any cluster you stand up new in 2026 is KRaft. Practically this means: fewer moving parts, faster controller failover, and much faster recovery when a broker with a lot of partitions restarts, because metadata is a log rather than a tree to be re-read.

What it does not mean is that Kafka became easy. KRaft removed a dependency; it did not remove partitions, rebalances, or the fact that consumer lag is still the metric that wakes you up. If a vendor's pitch is essentially 'KRaft made self-hosting simple', treat that as a claim to verify rather than a conclusion.

Sizing: partitions and throughput without the folklore

Partition count is the one design decision that is genuinely hard to undo, because increasing partitions on a keyed topic changes which partition a key hashes to, which breaks your ordering guarantee for existing keys. So it is worth ten minutes of arithmetic up front.

  1. Measure or estimate peak throughput for the topic, in messages per second and in bytes per second. Both matter — a topic doing many tiny messages and a topic doing few large ones stress different things.
  2. Measure how fast one consumer instance can actually process a message end to end, including whatever database write or API call it makes. This is almost always the real bottleneck, not Kafka.
  3. Divide peak throughput by single-consumer throughput. That's your minimum consumer count, and because one partition is consumed by at most one member of a consumer group, it's your minimum partition count too.
  4. Add headroom for growth, but not a lot. More partitions means more open file handles, more replication traffic, more metadata and slower rebalances. Doubling your estimate is prudent; multiplying it by fifty is a future incident.
  5. Decide retention deliberately, in hours or days, and write down why. 'Whatever the default was' is how storage bills happen.

The corollary people miss: adding consumer instances beyond your partition count does nothing. If you have 6 partitions and you scale your consumer deployment to 20 replicas, 14 of them sit idle holding a group membership and contributing to rebalance time. Partition count is your parallelism ceiling.

The two cost traps: cross-AZ replication and egress

Here is the thing that surprises people about a Kafka bill: a large fraction of it is often not Kafka. It's the network.

A standard production Kafka topic has replication factor 3 with replicas spread across three availability zones, because that's what survives an AZ failure. That means every byte you produce crosses an AZ boundary twice as it replicates. On the major clouds, inter-AZ traffic is billed in both directions. So your write path is multiplying your ingest volume by a constant before anything is even consumed.

Then the read path does it again. By default, a Kafka consumer reads from the partition leader, wherever that leader happens to be — which for two thirds of your partitions is a different AZ from your consumer. Kafka has supported follower fetching (rack-aware consumers reading from a local replica) for years, and it is the single highest-leverage cost fix available to most teams, but it requires that your consumers set a rack ID and that the provider exposes the configuration. Check both.

# A librdkafka-based consumer configured for the things that actually
# matter in production: rack-aware fetching, manual offset commits, and
# bounded rebalance disruption via the cooperative assignor.
from confluent_kafka import Consumer

consumer = Consumer({
    "bootstrap.servers": "pkc-example.eu-west-1.example.cloud:9092",
    "security.protocol": "SASL_SSL",
    "sasl.mechanisms": "PLAIN",
    "sasl.username": "<api-key>",
    "sasl.password": "<api-secret>",

    "group.id": "orders-sink",

    # Read from a replica in OUR availability zone instead of the
    # partition leader. This is the cross-AZ egress fix.
    "client.rack": "eu-west-1b",

    # Incremental rebalancing: adding a consumer moves only the
    # partitions that need to move, instead of stopping the world.
    "partition.assignment.strategy": "cooperative-sticky",

    # Commit only after we have durably handled the message. At-least-once
    # delivery, which means your handler must be idempotent.
    "enable.auto.commit": False,
    "auto.offset.reset": "earliest",

    # Bound how long a slow handler can stall the group before we are
    # evicted and the partitions are reassigned.
    "max.poll.interval.ms": 300000,
    "session.timeout.ms": 45000,
})

consumer.subscribe(["orders.v1"])

while True:
    msg = consumer.poll(timeout=1.0)
    if msg is None:
        continue
    if msg.error():
        raise RuntimeError(msg.error())

    handle(msg.value())          # must be idempotent
    consumer.commit(msg, asynchronous=False)
Before you sign anything, model your bill on three separate lines: broker/compute, retained storage, and network. Ask the vendor explicitly whether inter-AZ replication traffic and consumer egress are included in the quoted price or billed on top. The answer varies by vendor and sometimes by tier within one vendor.

The vendors, qualitatively

I'm deliberately not putting numbers on any of these. Managed streaming pricing changes often, is frequently tier-dependent, and every vendor has a different definition of what a 'unit' is — quoting figures here would be actively misleading within a quarter. Verify pricing and limits against each vendor's current docs before you commit to anything.

  • Confluent Cloud — Model: the commercial service from the company founded by Kafka's original authors; fully managed brokers plus the surrounding ecosystem (Schema Registry, ksqlDB, a large managed connector catalogue, Flink). Ops burden: lowest in the market; cluster sizing, rebalancing and upgrades are genuinely somebody else's problem, and the serverless-style tiers remove capacity planning entirely. Best for: teams who want the whole streaming platform rather than just a log, and who value the connector catalogue and schema governance more than the line item.
  • AWS MSK / MSK Serverless — Model: Apache Kafka running inside your AWS account's networking, so it lives in your VPC, uses IAM for auth and lands on your existing bill. Provisioned MSK gives you brokers to size; MSK Serverless removes broker sizing at the cost of tighter per-cluster limits. Ops burden: middling — AWS handles the hosts and patching, but partition planning, rebalancing strategy and lag monitoring are still yours. Best for: AWS-native shops where VPC-local networking and IAM integration outweigh the thinner ecosystem.
  • Redpanda Cloud — Model: a Kafka-API-compatible broker rewritten in C++ with no JVM and no ZooKeeper, using a thread-per-core architecture; your existing Kafka clients connect unchanged. Ops burden: low, and the self-hosted version is notably simpler than Kafka's — a single binary rather than a JVM plus tuning. Best for: latency-sensitive workloads and teams who want fewer moving parts, or who want the option of a credible self-hosted path with the same API.
  • Aiven for Apache Kafka — Model: open-source Apache Kafka managed across AWS, GCP, Azure, DigitalOcean and others, with a strong bring-your-own-cloud story and matching managed services for the rest of your stack. Ops burden: low for the cluster itself; you still own topic and partition design. Best for: multi-cloud or non-AWS deployments, and teams who explicitly want unmodified open-source Kafka rather than a reimplementation.
  • WarpStream — Model: the interesting architectural bet — a Kafka-compatible system with diskless, stateless agents that write directly to object storage (S3 and equivalents) instead of replicating between broker disks. That design deletes cross-AZ replication traffic and local disk from the cost model, trading it for higher write latency, since durability now means an object-store round trip. Ops burden: low, and the agents are genuinely stateless, which makes scaling trivial. Best for: high-throughput, latency-tolerant pipelines — log and telemetry ingestion, analytics feeds — where the network bill is the problem you're solving.
  • Upstash Kafka — Model: per-request, scale-to-zero Kafka with an HTTP/REST interface alongside the native protocol, which means you can produce and consume from runtimes that only speak fetch. Ops burden: effectively nil. Best for: edge functions, serverless handlers, side projects and low-volume event streams where paying for an idle cluster makes no sense. Verify current availability and limits — this product line has changed shape before.
  • Strimzi on Kubernetes (self-hosted) — Model: the CNCF operator for running Kafka on Kubernetes; declarative custom resources for clusters, topics and users, with KRaft support and rolling upgrade automation. Ops burden: highest by a wide margin — you own the storage classes, the rebalancing (via Cruise Control), the upgrades and the pager. Best for: teams with existing platform engineers, strict data-residency or air-gap requirements, or throughput large enough that managed pricing genuinely stops making sense.

One pattern worth naming: the market has split between 'Kafka as a product' (Confluent, Aiven) and 'the Kafka API on a different architecture' (Redpanda, WarpStream, Upstash). If you use Kafka as a plain durable log with standard clients, the second group is fully in play and often cheaper or simpler. If you depend on the surrounding ecosystem — Connect, Streams, ksqlDB, transactions, exactly-once semantics — verify each one specifically, because API compatibility is a spectrum and the edges are where the surprises live.

The honest section: most teams don't need Kafka

Kafka earns its complexity when you need at least two of these: retention and replay (a new consumer can read history from the beginning), per-key ordering, multiple independent consumer groups over the same stream, or throughput beyond what a single-node queue handles. If you need one of them, or none, there is almost certainly a smaller answer.

  • You need work distributed to workers, once each — that's a job queue. Postgres with SELECT ... FOR UPDATE SKIP LOCKED handles a genuinely surprising amount of throughput, and the jobs are transactional with the rest of your data.
  • You need a service to react when something happens — that's a webhook or a function trigger. A durable log is a heavy way to say 'call this endpoint'.
  • You need to buffer bursts so a slow downstream doesn't fall over — that's SQS, or a Postgres table with a claim column. Both are hours of work, not weeks.
  • You need to fan one event out to a handful of subscribers — that's SNS, Pub/Sub, or NOTIFY. You'll know you've outgrown it when you want replay, and that's the moment to reach for Kafka.
  • You need an audit trail — that's an append-only table with an index. It is queryable with SQL, which the log is not.
The best signal that you actually need Kafka is that you've already built something Kafka-shaped by accident and it's straining. The worst signal is an architecture diagram drawn before the first customer.

If you're in the second category, the good news is that the migration path later is fine. Consumers written against a queue abstraction port to Kafka reasonably cleanly. The reverse — unwinding a Kafka deployment you didn't need — is the painful direction, because by then three teams have built on the topics.

The half nobody sells you: hosting the consumers

Every vendor above sells you brokers. None of them run your consumers. And consumers are where most of the actual operational trouble lives, because a consumer is a long-lived process that must stay connected, hold a group membership, respond to rebalances, and not die quietly at 3am while lag climbs.

This is an awkward shape for a lot of modern hosting. Serverless function platforms are built around request-scoped execution with a hard timeout, which is precisely the wrong model for something that wants to hold a poll loop open indefinitely. So teams either bolt on a Kubernetes deployment purely to run three consumer processes, or they use an HTTP-bridge product and accept the cost model that comes with it.

This is where PandaStack fits, and I want to be exact about it: we do not host Kafka brokers. We host the long-lived processes that talk to them. A consumer on PandaStack is an ordinary process in its own Firecracker microVM with a full Linux userspace — it can hold a TCP connection to your broker for as long as it likes, run librdkafka, and use whatever client library you already have. Deploys are blue-green: the new consumer starts, joins the group, and the old one is torn down.

# Deploy a consumer as a long-running app. No timeout, no cold-start
# reconnect churn -- the poll loop just stays up.
pandastack apps create \
  --name orders-sink \
  --git https://github.com/acme/orders-sink \
  --branch main \
  --start "python -u consumer.py" \
  --env KAFKA_BOOTSTRAP=pkc-example.eu-west-1.example.cloud:9092 \
  --env KAFKA_CLIENT_RACK=eu-west-1b

# The sink database, alongside it.
pandastack databases create --label orders-sink-db --size 4g

The second half of a consumer is almost always a database write, and that's the other piece we run: managed Postgres, one instance per microVM, created in 30-90 seconds. Consumer and sink live on the same platform with a private connection string between them, which removes an entire category of cross-account networking work.

The scale-to-zero part is worth a caveat, because it cuts both ways. Our microVMs restore from a snapshot with a p50 of 179ms and a p99 around 203ms, and a first cold boot is about 3 seconds — so idling a workload down to nothing and bringing it back is cheap. That is excellent for the surrounding cast: the replay job you run occasionally, the backfill worker, the schema-migration task, the per-branch staging consumer for a pull request. It is not what you want for a primary consumer in a group, because a process that scales to zero leaves the consumer group, triggers a rebalance, and lets lag build. Run the steady-state consumers as always-on apps; use scale-to-zero for the bursty work around them.

# A one-off replay: spin a sandbox, drain a topic range into the sink,
# throw the machine away. This is the shape scale-to-zero is good at.
from pandastack import Sandbox

sbx = Sandbox.create(template="base", ttl_seconds=600)

sbx.exec("pip install --quiet confluent-kafka psycopg[binary]")
sbx.filesystem.write("/app/replay.py", open("replay.py").read())

result = sbx.exec(
    "cd /app && python replay.py "
    "--topic orders.v1 --from-offset 4210000 --to-offset 4213500"
)
print(result.stdout)
Each PandaStack host pre-allocates 16,384 /30 subnets, so a fan-out of throwaway consumers for a backfill is a networking non-event — you're not queueing on IP allocation.

Choosing, in about fifteen minutes

  1. Write down which of the four Kafka properties you actually need: replay, per-key ordering, multiple independent consumer groups, or throughput beyond a single-node queue. Fewer than two means look at a queue instead and stop here.
  2. Estimate your steady-state ingest in bytes per second and multiply by your retention window and replication factor. That number, not the per-hour broker price, is what will surprise you.
  3. Ask each vendor directly whether cross-AZ replication and consumer egress are inside or outside the quoted price, and whether follower fetching (client.rack) is supported.
  4. Check whether tiered storage is available on the tier you can actually afford, and how reads from the tiered portion are billed.
  5. If you use Kafka as a plain log, price the Kafka-compatible alternatives too — Redpanda for latency, WarpStream for throughput at low network cost. If you depend on Connect, Streams or exactly-once semantics, verify each one explicitly rather than trusting 'Kafka-compatible'.
  6. Decide where the consumers will run before you sign, not after. That decision has bitten more teams than the broker choice has.

The summary

Confluent Cloud if you want the whole streaming platform and the ecosystem is the point. MSK if you're AWS-native and want it in your VPC on your existing bill. Redpanda if you want the Kafka API with fewer moving parts and better tail latency. Aiven if you want unmodified open-source Kafka across clouds. WarpStream if your bill is really a network bill and you can tolerate object-storage write latency. Upstash if your volume is small and spiky and your code lives at the edge. Strimzi if you have platform engineers and a residency requirement. And seriously consider not running Kafka at all — a Postgres queue and a webhook cover more of the real world than the architecture diagrams admit.

Whichever you pick, the brokers are half the problem. The consumers have to live somewhere, stay connected, and get deployed without dropping the group on the floor. That half is the one we work on.

Frequently asked questions

Do I still need ZooKeeper to run Kafka in 2026?

No. KRaft mode moved cluster metadata into Kafka itself, managed by a Raft quorum of controller nodes, which removes the separate ZooKeeper ensemble entirely. ZooKeeper support was deprecated in Kafka 3.5 and removed in the 4.x line, so any new cluster you create today is KRaft-based, and every managed provider has migrated. The practical benefits are fewer processes to operate, faster controller failover and much faster broker restart when a broker owns many partitions. What KRaft does not remove is the rest of Kafka's operational surface — partition planning, consumer group rebalances and lag monitoring are unchanged.

Why is my managed Kafka bill so much higher than the broker price?

Almost always network and storage rather than compute. A replication factor of 3 spread across availability zones means every produced byte crosses an AZ boundary twice during replication, and inter-AZ traffic is billed in both directions on the major clouds. Then consumers, by default, read from the partition leader — which for roughly two thirds of partitions sits in a different AZ from the consumer, billing egress again. Retention compounds it: a busy topic held for a week and replicated three ways is a lot of continuously-billed disk. Enabling rack-aware follower fetching on consumers and shortening retention (or enabling tiered storage) are the two fixes with the largest effect.

How many partitions should a Kafka topic have?

Start from consumer throughput, not from broker capacity. Measure how many messages one consumer instance processes end to end per second, including its database writes and API calls, then divide peak topic throughput by that figure. Because a partition is consumed by at most one member of a consumer group, that quotient is both your minimum consumer count and your minimum partition count. Add modest headroom for growth — doubling is prudent — but resist large round numbers: more partitions means more file handles, more replication traffic, more metadata and slower rebalances. Getting it wrong upward is expensive; getting it wrong downward is worse, since increasing partitions later changes key-to-partition mapping and breaks per-key ordering for existing keys.

Should I use Kafka or a job queue?

Kafka earns its complexity when you need at least two of: retention with replay so a new consumer can read history, per-key ordering, multiple independent consumer groups reading the same stream, or throughput beyond what a single-node queue handles. If you need one or none of those, a job queue is the better answer — Postgres with SELECT ... FOR UPDATE SKIP LOCKED handles far more throughput than people expect, keeps jobs transactional with the rest of your data, and is inspectable with ordinary SQL. The migration from a queue abstraction to Kafka later is straightforward; unwinding an unnecessary Kafka deployment after three teams have built on the topics is the painful direction.

Does PandaStack host Kafka?

No, and we do not plan to — we do not run Kafka brokers. What we host is the other half: the producers, consumers and stream processors that talk to your broker, plus the managed Postgres those consumers typically write into. A consumer runs as an ordinary long-lived process in its own Firecracker microVM with a full Linux userspace, so it can hold a TCP connection open indefinitely, use librdkafka or any standard client, and get deployed blue-green so the new instance joins the group before the old one leaves. Pair it with a managed Postgres sink, created in 30 to 90 seconds, on the same platform. Use always-on apps for steady-state consumers and our scale-to-zero sandboxes for the bursty work around them — replays, backfills and per-branch staging consumers.

Keep reading

Run code in a microVM in one API call.

49ms p50 cold start. Fork, snapshot, and scale to zero.

Start free
Written by Ajay Kumar, Founder, PandaStack.