Cost Optimization in Real-Time Streaming Systems
Introduction
Cost Optimization in Real-Time Streaming Systems
Introduction
Real-time streaming systems powered by Apache Kafka and Apache Flink have become the backbone of modern data infrastructure. They enable businesses to react to events as they happen — fraud detection, live dashboards, personalized recommendations, and operational alerting all depend on sub-second data processing.
However, this power comes at a steep cost. Running Kafka clusters with days of retention, over-provisioned Flink executors, and redundant computations across multiple consumers can easily balloon cloud bills into six or seven figures annually. The irony? Most of this spend is waste — paying for capacity that sits idle or data that nobody reads.
In this article, I’ll share four battle-tested strategies that can reduce your real-time infrastructure costs by 40–70% while maintaining (or even improving) system reliability:
-
Kafka data minimization — keep only hot data on brokers, archive to S3
-
Lag-based auto-scaling — dynamically right-size Flink executors
-
On-the-fly aggregation — reduce data volume at the source
-
Medallion architecture — compute once, serve many consumers
Strategy 1: Kafka Data Minimization + S3 Archival
The Problem
Most teams configure Kafka with retention periods of 7–30 days “just in case.” This means every broker needs enough disk to hold a month of data across all topics. For high-throughput systems processing millions of events per second, this translates to terabytes of expensive EBS storage attached to each broker node.
The reality? Real-time consumers process events within seconds of arrival. That 7-day retention window exists only for rare replay scenarios — debugging, backfills, or disaster recovery. You’re paying premium SSD prices to store data that’s accessed once in its lifetime.
The Solution
Separate hot and cold data paths. Keep only 1–2 hours of retention on Kafka (enough for consumer recovery) and continuously sink all data to S3 in columnar format (Parquet/ORC) for cheap long-term storage and on-demand replay

Implementation Details
• Kafka Connect S3 Sink Connector: Continuously exports topic data to S3 in Parquet format, partitioned by date/hour for efficient querying
• Retention Configuration: Set retention.ms to 2–4 hours and cleanup.policy=delete on production topics
• Replay Mechanism: Use a lightweight consumer that reads from S3 and re-publishes to a replay topic when needed
• Cost Comparison: S3 Standard at $0.023/GB/month vs Kafka EBS (gp3) at $0.08–$0.10/GB/month — a 4–5x reduction in storage cost
Results
A typical high-throughput system writing 500GB/day to Kafka with 7-day retention holds 3.5TB per broker. Reducing to 2-hour retention drops this to ~42GB — an 88% reduction in Kafka storage costs. The S3 archive costs a fraction and enables analytics queries via Athena/Spark that weren’t possible before.
Strategy 2: Lag-Based Auto-Scaling of Flink Executors
The Problem
Most Flink deployments are sized for peak load and left running 24/7. If your peak is 10x your average (common for e-commerce, media, fintech), you’re paying for 10x resources during off-peak hours — nights, weekends, and holidays.
Traditional auto-scaling based on CPU/memory doesn’t work well for streaming because these metrics lag behind the actual processing backlog. By the time CPU spikes, you’re already accumulating consumer lag and potentially violating SLAs.
The Solution
Use consumer lag (the difference between the latest offset and the consumer’s committed offset) as the primary scaling signal. Lag is a leading indicator — it grows before CPU pressure does, giving you time to scale up proactively. When lag drops below a threshold, scale down to save costs.

Implementation Details
• Monitoring: Export kafka_consumer_group_lag metric to Prometheus. Alert on rate of change, not absolute value
• Scale-up trigger: When lag exceeds 10K messages (or lag growth rate > 1K/sec), add TaskManagers. Use Flink’s Reactive Mode or Kubernetes HPA with custom metrics
• Scale-down trigger: When lag stays below 1K for 10+ minutes, remove TaskManagers. Add a cooldown period to prevent flapping
• Graceful scaling: Use Flink savepoints during scale-down to preserve exactly-once semantics. New TaskManagers restore from the latest checkpoint
Results
For a system with 10x peak-to-trough ratio, lag-based scaling typically achieves 40–60% reduction in compute costs. The system runs with 2 executors during quiet hours and scales to 10+ during peak, matching capacity to actual demand in real-time.
Strategy 3: On-the-Fly Aggregation
The Problem
Many real-time pipelines treat every event as sacred, passing raw granular data through multiple processing stages and storing it for downstream queries. But most consumers don’t need individual events — they need aggregates: counts per minute, averages per region, totals per product category.
Processing 10 million raw events per minute when your dashboard only displays 50 aggregated data points is a massive waste of compute and storage.
The Solution
Push aggregation as close to the source as possible. Use Flink’s windowing operators to pre-aggregate data before it hits storage or downstream consumers. This reduces data volume by 100–1000x while providing the exact metrics consumers need

Implementation Details
• Tumbling windows: Fixed 1-minute buckets for real-time metrics (COUNT, SUM, AVG per dimension key)
• Incremental aggregation: Use ReduceFunction instead of ProcessWindowFunction to minimize state — each window holds one accumulator, not all events
• Multi-level aggregation: Aggregate at source (1-min), then roll up to 5-min, 1-hour, and 1-day granularities downstream
• Late data handling: Allow 30-second lateness with a side output for late events. Recompute affected windows on arrival
Results
A clickstream pipeline processing 10M events/min reduced to 10K aggregated records/min — a 1000x reduction in downstream data volume. This cut Flink executor count from 10 to 2, reduced state size by 95%, and made dashboard queries 50x faster.
Strategy 4: Data validations on the Producer Side
The Problem
When data producers (applications, services, or upstream systems) send raw data to the central data platform, errors, inconsistencies, and schema violations often slip through. This results in downstream consumers (dashboards, analytics, ML models) spending significant resources on cleaning, validating, and correcting data. Multiple teams may duplicate validation logic, leading to wasted effort and inconsistent data quality.
The Solution
Shift data validation upstream to the producer side. Enforce schema checks, business rules, and quality constraints before data enters the central data lake or warehouse. This ensures only high-quality, consistent data is ingested, reducing downstream complexity and improving trust in shared datasets.
Implementation Details
- Producer Validation Layer: Integrate validation logic directly into producer applications or ETL pipelines. Use schema enforcement (e.g., Avro, Protobuf), data quality checks (nulls, ranges, referential integrity), and business rule validation.
- Validation Feedback Loop: If data fails validation, provide immediate feedback to producers for correction, preventing bad data from entering the system.
- Centralized Validation Registry: Maintain a registry of validation rules and schemas, versioned and accessible to all producers, ensuring consistency across teams.
- Monitoring & Alerting: Track validation failures and alert producers and data engineering teams for rapid resolution.
Results
By validating data at the source, downstream consumers receive clean, reliable datasets, eliminating redundant validation steps. Data quality issues are caught early, reducing operational overhead and improving confidence in analytics. Adding new consumers is simplified, as they can trust the integrity of ingested data without custom validation logic.
Strategy 5: Medallion Architecture for Multi-Consumer Reports
The Problem
When multiple teams or dashboards consume the same data, a common anti-pattern emerges: each consumer runs its own aggregation pipeline independently. Five dashboards viewing sales data means five separate Flink jobs doing essentially the same computation. This is both expensive and operationally fragile.
The Solution
Implement a medallion architecture (Bronze → Silver → Gold) where data is progressively refined through layers. The Gold layer contains pre-computed, business-level aggregates that serve all consumers. Compute once, serve many.
Implementation Details
• Bronze layer: Raw event ingestion into a data lake (S3/Delta Lake). Append-only, full fidelity, partitioned by event time
• Silver layer: Cleaned, deduplicated, enriched data with enforced schemas. Join with dimension tables (users, products, regions)
• Gold layer: Pre-computed aggregates optimized for specific business questions. Materialized views refreshed on a schedule or trigger
- Serving layer: Gold data served via Redis/DynamoDB for sub-ms latency, or directly queried via Presto/Trino for ad-hoc analysis
Results
Consolidating 5 independent aggregation pipelines into a single medallion architecture reduced total compute by 60–80%. Query latency dropped from seconds to milliseconds for dashboard consumers, and adding a new consumer became a configuration change instead of a new pipeline.
Where to Start
Start with the highest-impact, lowest-risk change for your system:
• If storage is your top cost: Start with Kafka retention reduction + S3 sink
• If compute is over-provisioned: Start with lag-based auto-scaling
• If you have high event volume with low query diversity: Start with on-the-fly aggregation
• If multiple teams consume the same data: Start with medallion architecture
Key Takeaways
• Real-time doesn’t mean expensive — most cost comes from waste, not from the streaming itself
• Separate hot and cold paths — don’t pay premium prices for data that’s rarely accessed
• Match capacity to demand — auto-scale based on actual backlog, not worst-case projections
• Reduce data early — every byte you don’t process downstream is pure savings
• Compute once, serve many — shared layers beat independent pipelines every time
The best optimization is the one you implement first. Pick one strategy, measure the impact, and iterate.
메타데이터
- post_id
- 27fecae6d267
- slug
- cost-optimization-in-real-time-streaming-systems-27fecae6d267
- url
- https://medium.com/@jatinagrawal_93108/cost-optimization-in-real-time-streaming-systems-27fecae6d267
- canonical_url
- https://medium.com/@jatinagrawal_93108/cost-optimization-in-real-time-streaming-systems-27fecae6d267
- author_url
- https://medium.com/@jatinagrawal_93108
- status
- ok
- fetched_at
- 2026-06-09 15:37:30