Every self-hosted platform eventually hears it from a tenant: "can you just run our event bus?" It sounds like a small favor — Kafka is a single binary these days, after all — but it is really a request to take on a stateful distributed system with its own storage math, rebalance rituals, and noisy-neighbor politics.
The honest answer starts with a price tag, so here it is up front: for one typical small-tenant event bus, self-hosting Kafka on Kubernetes via Strimzi runs roughly $950–$1,350 a month all-in once you count labor, a managed MSK cluster lands around $700–$900, Confluent Cloud around $200–$400, and a serverless option around $50–$200. The rest of this post shows the arithmetic behind those numbers, what Strimzi automates and what it leaves on your plate, and the decision checklist for when a platform that does not offer managed data services should run Kafka anyway.
The ask, priced in one table
Comparisons without a defined workload are vibes, so fix a reference workload first: one small tenant event bus doing about 10 GB of ingress a day, 7-day retention, replication factor 3, a few dozen partitions. That is roughly 300 GB a month of throughput and about 210 GB of raw log storage before headroom — the shape of an early event-driven service, not a data-platform firehose.
| Monthly cost line | Strimzi, self-hosted on owned hardware | AWS MSK provisioned | Confluent Cloud | Serverless (Redpanda / Upstash) |
|---|---|---|---|---|
| Compute | ~$150–$300 (3 owned-class machines, amortized share) | ~$460 (3 brokers at ~$0.21/hr) | $0 base on usage-priced tiers | $0 base |
| Storage / throughput | Disks already owned; ~300–500 GB provisioned | ~$50–$100 (EBS + replication traffic) | ~$30–$90 (300 GB at ~$0.10–$0.30/GB) + storage | Metered per message/GB |
| Ops labor (stated: ~6 hrs/mo self-hosted, ~1–2 hrs managed, at $125/hr loaded) | ~$750 | ~$150–$250 | ~$125 | ~$60 |
| Illustrative total | ~$950–$1,350 | ~$700–$900 | ~$200–$400 | ~$50–$200 |
| Delta vs cheapest | +~$900 | +~$650 | +~$150 | baseline |
Two caveats before anyone screenshots the table. First, these are illustrative estimates from public price points, not quotes: MSK broker-hour pricing starts around $0.21, Confluent throughput bills roughly $0.10–$0.30 per GB, Upstash charges per message plus $0.25 per GB of storage — all moving targets, but the ranking is stable across recent managed-Kafka comparisons.
Second, the labor row is doing most of the work in the self-hosted column, deliberately: at this throughput, you are not buying Kafka capacity, you are buying someone to run Kafka. Six steady-state hours a month for patching, rebalance reviews, quota tuning, and the occasional page is conservative — and the setup month runs three to five times that.
Now the sensitivity, because one point is not an answer. Throughput is the variable that flips the ranking. Below about 1 GB a day, serverless wins outright — the self-hosted fixed costs never amortize. At ten times the reference workload (100 GB a day), throughput-metered bills scale linearly into the low thousands while the self-hosted marginal cost stays near zero, and the ranking inverts: owned hardware plus Strimzi becomes cheapest in cash terms, with MSK close behind.
Retention is the second variable, and it bites through storage. Stretching the reference workload from 7-day to 30-day retention multiplies raw log storage from ~210 GB to ~900 GB, which forces a disk tier jump on self-hosted hardware and quietly doubles the storage line on every metered option.
The verdict: at small-tenant scale, "just run Kafka" is cheapest as someone else's serverless problem and most expensive as your own StatefulSet — unless you already run the fleet and the labor is sunk. Which is exactly the position a self-hosted PaaS is in, so keep reading.
What Strimzi actually gives you
Strimzi is the reason this conversation is even practical. It is a CNCF incubating project — sandbox since 2019, promoted to incubation in February 2024 — that implements the Kubernetes operator pattern for Apache Kafka: you declare clusters, topics, and users as custom resources, and controllers reconcile reality to match.
The project has three operators that map neatly onto the jobs a Kafka admin used to do by hand. The Cluster Operator deploys and configures brokers (now in KRaft mode, with ZooKeeper gone — more on that below), handles TLS certificate generation and rotation, and performs rolling upgrades. The Topic Operator turns KafkaTopic custom resources into real topics with declared partitions and retention. The User Operator turns KafkaUser resources into SCRAM or mTLS credentials with ACLs. A minimal TLS-encrypted three-broker cluster is genuinely a single Kafka manifest away.
Two recent developments made the operator story materially better. First, Apache Kafka 4.0 removed ZooKeeper entirely — KRaft has been production-ready since 3.3, 3.9 was the last ZooKeeper-capable bridge release, and 4.x is KRaft-only. Every pre-2025 "running Kafka" guide that prices a three-node ZooKeeper ensemble alongside the brokers is now overstating the footprint by nearly half; Strimzi runs KRaft natively, so a modern deployment is just the brokers.
Second, Strimzi integrates with Cruise Control for partition rebalancing, which turns the scariest day-2 operation — moving replicas after a broker loss or a scale event — from a hand-computed replica-assignment exercise into a declared optimization goal.
What Strimzi does not do is the part tenants never see: capacity planning, partition-count and retention policy per topic, per-tenant quota policy, backup/restore of topic data beyond replication, and being on call when a broker stops following the ISR at 3 AM. The operator automates the mechanics; the judgment — and the pager — stays with you. That residue is precisely the six-hours-a-month labor row in the table.
The real bill for "just run Kafka"
Three cost centers sit behind that labor row, each with its rule of thumb.
StatefulSet storage sizing and retention math. Kafka storage is ingress × retention × replication factor, plus headroom you will actually need because brokers stop accepting writes when disks fill. Reference workload: 10 GB/day × 7 days × RF3 ≈ 210 GB raw, so provision ~300–500 GB across the brokers — call it 150 GB per broker with room for segment churn and a rebalance in flight. The trap is retention creep: a tenant asking for 30 days "just for replay" quadruples raw storage to ~900 GB, which on owned hardware means bigger disks ordered weeks ago and on JBOD layouts means re-striping volumes. Rule of thumb: price retention, not just throughput, and put the retention default in the KafkaTopic template so every new topic inherits a bounded number instead of negotiating its own.
Partition-rebalance and upgrade ops cadence. Brokers are pets that pretend to be cattle. Every broker replacement, version upgrade, or scale event triggers partition rebalancing — data physically moving between brokers while serving reads and writes — and Strimzi plus Cruise Control make this declarative but not free: someone reviews the rebalance proposal, schedules it outside peak, and watches ISR health until it converges. Budget a couple of hours per event and a standing monthly patch-and-review window; Kafka ships often enough that "we upgrade quarterly" still means four supervised rolling restarts a year, each touching every tenant topic on the bus. Rule of thumb: if your team cannot absorb one supervised rolling restart per quarter, you cannot offer a shared bus.
Per-tenant throughput isolation. This is the one that turns a favor into an incident. One tenant's traffic spike becomes everyone's latency unless the bus enforces quotas: Kafka supports produce/fetch byte-rate quotas per client-id, and on a shared Strimzi cluster those quotas are the only thing standing between tenants. Concretely, that means every tenant gets a dedicated KafkaUser with quota annotations, a topic-naming convention the ACLs can match, and a dashboard that shows per-tenant produce bytes — none of which exists by default. Rule of thumb: no quotas, no multitenancy — a shared bus without client quotas is a single-tenant cluster with extra victims.
The honest alternatives
A platform team that runs the numbers above sometimes concludes the right answer is "not us" — and the BYO-data-layer stance this industry has settled on for Postgres applies to Kafka too. Four options, honestly priced:
- AWS MSK provisioned (~$700–$900/mo all-in at reference scale) buys managed brokers with in-place ZooKeeper-to-KRaft upgrades and IAM auth, while leaving topic design, quotas, and client ops to you. It is the smallest step down in control for the largest step down in paging.
- Confluent Cloud (~$200–$400/mo at reference scale, scaling linearly past it) buys the full managed surface — Schema Registry, connectors, ksqlDB — metered on throughput. The entry tiers start near zero, which makes it the cheapest honest answer for a tenant below ~10 GB/day who still wants real Kafka semantics.
- Redpanda Cloud serverless (free to start, usage-metered) buys Kafka-API compatibility on a C++ engine with dramatically lower idle cost. The tradeoff is ecosystem edges: anything that reaches past the Kafka protocol into broker internals may notice the difference.
- Upstash Kafka (10,000 messages a day free; then per-message plus $0.25/GB storage) buys HTTP-friendly serverless Kafka for workloads that are bursty or tiny. At reference scale it sits in the tens to low hundreds of dollars — the table's baseline for a reason.
The pattern across all four: below the reference workload, metered options win because self-hosting has a floor; above roughly 10x, the floor wins because metering has no ceiling. A PaaS that documents this breakeven gives tenants a better answer than either a flat no or an unpriced yes.
Drawing the platform boundary
"We don't run managed data services" is a legitimate platform boundary — managed databases are explicitly out of scope for lean PaaS teams — but a boundary with no documented Kafka answer just reroutes the tenant to shadow infrastructure. Here is the checklist version of this post's math; publish something like it instead of staying silent:
- Under ~1 GB/day? Point the tenant at serverless (Redpanda or Upstash). Your cost to operate anything exceeds their entire bill.
- 1–30 GB/day with standard Kafka needs? Recommend Confluent Cloud or MSK, and offer to manage the client side (topics, ACLs, quotas) as code. You keep the GitOps story without the broker pager.
- Steady high throughput, long retention, or data-residency constraints? Run Strimzi on your own fleet — this is where the fixed costs amortize and control matters. Require declared retention, per-tenant quotas, and a quarterly upgrade window as conditions of the offering.
- Can your team absorb one supervised rolling restart per quarter? If no, stop at option 2 regardless of throughput. The constraint is people, not machines.
- Is the tenant asking for Kafka-protocol compatibility or Kafka-the-ecosystem? Protocol-only workloads (produce/consume) are portable to Redpanda; Connect, Schema Registry, and ksqlDB workloads pin you to real Kafka and narrow the field.
The meta-point: each branch is a documented, priced answer. Tenants accept "no, and here is the option that costs you $80 a month" far better than "no" — and better than a silent yes that pages your team.
The takeaway
Kafka on Kubernetes crossed from heroic to routine when two things happened: Strimzi matured into a CNCF-backed operator that handles certificates, upgrades, and rebalancing declaratively, and KRaft deleted the ZooKeeper half of every deployment diagram. What remains expensive is not the software but the stewardship — storage math, rebalance supervision, and per-tenant isolation — and that cost is now quantifiable enough to put in a table and a policy. Price the ask, document the boundary, and "just run our event bus" becomes a routing decision instead of a trap.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



