ETL pipelines used to run once a night. That schedule worked for monthly reports, but today's dashboards demand data that's minutes old, and event-driven applications need sub-second latency. Yet batch processing hasn't disappeared—it still powers many financial reconciliations, historical analytics, and compliance audits. The question for most teams isn't which one to pick, but how to balance both without building two separate, unmaintainable systems.
This guide walks through the decision criteria, common hybrid architectures, and the risks that appear when you try to mix batch and streaming without a plan. We'll focus on practical patterns, not vendor pitches, so you can adapt these ideas to your own stack.
Who Must Choose and Why the Timeline Matters
Every team that manages data pipelines eventually faces this fork. Maybe your nightly batch job now takes six hours because data volume doubled. Maybe a business stakeholder saw a real-time dashboard demo and wants the same for your warehouse. Or maybe you're building a new product feature that needs fresh data to trigger alerts or personalization.
The pressure to move toward real-time is real, but it's not universal. Batch processing remains the right choice for many workloads—especially those where completeness and consistency matter more than speed. The key is to identify which parts of your pipeline genuinely need low latency and which can stay on a schedule. We've seen teams waste months trying to stream everything, only to discover that 80% of their consumers were fine with hourly updates.
Start by mapping your data consumers and their latency requirements. Ask: what's the maximum acceptable delay between an event occurring and it being available for query or action? For a fraud detection model, that might be seconds. For a weekly sales report, hours or even a day is fine. Once you have that map, you can design a pipeline that uses the right tool for each path.
Common Triggers for Revisiting Your ETL Approach
Several signals indicate it's time to evaluate your current balance:
- Batch windows are shrinking because data grows faster than your nightly job can process.
- Business users complain that dashboards show stale numbers during the day.
- You need to trigger actions (emails, alerts, API calls) based on recent events, not just store them.
- Your data sources now produce real-time streams (e.g., clickstream, IoT sensors, CDC logs) that you currently batch-load, losing the freshness advantage.
If none of these apply, your batch system might be fine. Don't add complexity without a clear benefit.
Option Landscape: Three Approaches to Mixing Batch and Stream
There's no single right architecture, but most successful implementations fall into one of three patterns. Each has strengths and trade-offs, and you can combine them within the same pipeline.
Pattern 1: Lambda Architecture
Lambda runs two parallel paths—a speed layer for real-time processing and a batch layer for comprehensive, accurate results. A serving layer merges outputs from both. This pattern is well-understood and works when you need both low latency and high accuracy. The downside is operational complexity: you maintain two codebases, two processing engines, and two sets of logic that must produce consistent results.
Pattern 2: Kappa Architecture
Kappa simplifies by using a single streaming pipeline for all data. Batch is simulated by replaying the stream from a log (like Kafka) to reprocess historical data. This reduces code duplication but requires that your streaming engine can handle large-scale reprocessing efficiently. It works best when your streaming framework supports exactly-once semantics and stateful operations.
Pattern 3: Hybrid Micro-Batch with Stream Ingestion
Many teams adopt a middle ground: ingest data via a streaming bus (Kafka, Kinesis) but process it in micro-batches (every few seconds to minutes) using tools like Spark Structured Streaming or Flink. This gives near-real-time freshness without the complexity of true event-at-a-time processing. It's a pragmatic choice when your downstream systems can tolerate a few seconds of delay.
We've seen teams succeed with each pattern. The choice depends on your latency needs, team skill set, and existing infrastructure. Don't pick an architecture because it's trendy—pick it because it fits your constraints.
Comparison Criteria: How to Evaluate Your Options
To choose between these patterns, you need a consistent set of criteria. We recommend evaluating on five dimensions:
- Latency requirement: What's the maximum acceptable delay? True streaming (sub-second) pushes you toward Kappa or Lambda with a speed layer. Micro-batch works for delays of 1–60 seconds. Batch is fine for minutes or hours.
- Data volume and velocity: High-volume streams (millions of events per second) may require careful partitioning and state management. Batch systems can handle volume by scaling horizontally, but they add latency.
- Consistency and accuracy needs: If you need exactly-once processing and the ability to correct historical data, batch or Lambda with a robust batch layer is safer. Pure streaming requires strong exactly-once guarantees from your engine.
- Operational complexity: Lambda is the most complex to operate. Kappa reduces code duplication but demands a mature streaming platform. Hybrid micro-batch is often the easiest to adopt for teams with batch experience.
- Cost: Streaming infrastructure (Kafka clusters, long-running compute) can be more expensive than scheduled batch jobs. Micro-batch can balance cost and freshness.
Score each pattern against these criteria for your specific use case. There's no universal winner—only the best fit for your constraints.
Trade-Offs in Detail: When Each Pattern Shines and Struggles
Let's go deeper into the practical trade-offs. We'll walk through a composite scenario to illustrate.
Imagine a retail company that wants real-time inventory dashboards for store managers, plus nightly financial reconciliation. The inventory data comes from point-of-sale systems as a stream of transactions. The financial data includes returns, discounts, and taxes that must be perfectly accurate.
Lambda approach: The speed layer processes each sale event to update inventory counts within seconds. The batch layer runs overnight, reconciling all transactions against the general ledger. The serving layer merges both, showing near-real-time counts but using batch results for final numbers. This works well but requires maintaining two pipelines. The team must ensure that the speed layer's logic matches the batch layer's logic—a common source of discrepancies.
Kappa approach: All transactions go into a Kafka topic. A streaming job (Flink or Kafka Streams) updates inventory state and also writes raw events to a data lake. For financial reconciliation, the same streaming job reprocesses the entire topic from the beginning, applying corrections. This eliminates code duplication but demands that the streaming engine handle large-scale reprocessing without performance degradation. If the reprocessing takes too long, the nightly batch window may be missed.
Hybrid micro-batch: The team uses Kafka for ingestion and Spark Structured Streaming with a 10-second micro-batch for inventory updates. For financial reconciliation, a separate nightly Spark batch job reads from the same Kafka topic (or from Parquet files in the data lake). This is simpler to operate than Lambda, and the 10-second delay is acceptable for store managers. The main risk is that micro-batch may not be fast enough for fraud detection or other sub-second use cases.
Each approach has a different failure mode. Lambda can suffer from logic drift between layers. Kappa requires careful tuning for reprocessing. Micro-batch may not meet the strictest latency SLAs. Document these risks and test them before committing.
Implementation Path: Steps to Build a Balanced Pipeline
Once you've chosen a pattern, follow these steps to implement it without breaking existing systems.
Step 1: Decouple Ingestion from Processing
Use a message bus or event log (Kafka, Pulsar, Kinesis) as the ingestion layer. This allows you to change processing logic without touching data sources. It also enables replay for reprocessing and backfilling.
Step 2: Define Data Contracts
Agree on schemas and semantics for each stream. Use schema registry to enforce compatibility. Without contracts, downstream consumers break when the source changes—a common pain point in streaming systems.
Step 3: Start with One Use Case
Don't try to migrate all pipelines at once. Pick a single stream that benefits from lower latency (e.g., real-time dashboard) and build a streaming pipeline for it. Keep the rest batch. This limits risk and lets your team learn.
Step 4: Implement Monitoring for Both Paths
Track latency, throughput, and error rates for each pipeline. For streaming, monitor lag (how far behind the stream your processing is). For batch, monitor job duration and failure rates. Set alerts for anomalies.
Step 5: Plan for Reprocessing
Eventually, you'll need to reprocess historical data due to logic changes or data quality fixes. Design your streaming pipeline to support replay from a specific offset or timestamp. Test reprocessing regularly.
Risks of Choosing Wrong or Skipping Steps
Mistakes in architecture decisions can lead to costly rewrites. Here are the most common risks and how to avoid them.
Over-Engineering for Real-Time
The biggest risk is building a full streaming pipeline when batch would suffice. You add complexity, cost, and debugging difficulty for little benefit. Guard against this by rigorously questioning latency requirements. If a stakeholder says they need real-time, ask what decision they'll make differently with data that's one second old versus one hour old. Often, the answer reveals that batch is fine.
Underestimating State Management
Streaming pipelines often need to maintain state (e.g., running counts, session windows). State management is hard—you need to handle failures, exactly-once semantics, and state size limits. Teams new to streaming frequently underestimate this and end up with inconsistent results.
Ignoring Data Quality in Streams
Batch pipelines can afford to clean and validate data before loading. Streaming pipelines must handle bad data in real time, which is more challenging. Design your stream processing to filter, transform, or route bad records to a dead-letter queue without blocking the main flow.
Neglecting Cost Monitoring
Streaming compute runs continuously, unlike batch jobs that run for a few hours. Costs can balloon if you don't monitor and optimize. Use auto-scaling, right-size your cluster, and consider spot instances for reprocessing jobs.
Frequently Asked Questions
Can I use batch and streaming together without two separate pipelines?
Yes, with a unified platform like Apache Flink or Spark Structured Streaming that supports both batch and stream processing modes. You can write one job that runs in streaming mode for fresh data and switches to batch mode for historical reprocessing. This reduces code duplication.
Do I need a message broker like Kafka to start streaming?
Not necessarily. You can stream from databases using change data capture (CDC) tools like Debezium, or from file-based sources. However, a message broker provides durability, replayability, and decoupling—benefits that become important as you scale.
How do I handle late-arriving data in streaming?
Use watermarks and allowed lateness in your streaming engine. Define a threshold for how late an event can arrive and still be included in windowed aggregations. Events that arrive after the threshold can be handled separately (e.g., sent to a correction stream).
What's the best way to test a streaming pipeline?
Unit test your transformation logic with mock streams. Integration test with a small Kafka cluster or embedded broker. For end-to-end testing, replay a known dataset and compare output to expected results. Chaos engineering (injecting failures) helps validate resilience.
Recommendation Recap Without Hype
There is no one-size-fits-all architecture for ETL in the age of real-time. The right approach depends on your latency needs, data characteristics, and team capabilities. Start by mapping your consumers and their tolerance for delay. Use that map to decide which data paths need streaming and which can stay batch.
For most teams, a hybrid approach works best: ingest everything through a streaming bus, process latency-sensitive streams in near-real-time (micro-batch or streaming), and keep batch for heavy transformations and historical reconciliation. Avoid Lambda unless you have a clear need for both speed and accuracy that cannot be met by a single pipeline. Kappa is elegant but requires a mature streaming platform.
Finally, invest in monitoring, data contracts, and reprocessing capabilities early. These fundamentals make it easier to evolve your architecture as requirements change. Start small, validate with real users, and expand only when the value is proven.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!