8 min read

Data Architecture Design: Lambda vs. Kappa

Modern data architecture requires robust frameworks to handle both real-time streaming data and massive historical batch data. Two of the most prominent architectural patterns for this are the Lambda Architecture and the Kappa Architecture.


1. Lambda Architecture

Lambda Architecture is a big data design pattern that handles massive streams of incoming data by dividing the work into two paths: one for maximum accuracy (slow, bulk processing) and one for maximum speed (fast, real-time processing).

Think of it like managing a popular restaurant:

  • The Batch Layer is the prep kitchen cooking large stocks and sauces overnight. It takes hours, but it's thorough and precise.
  • The Speed Layer is the line cook whipping up quick ingredients on the fly as orders come in right now.
  • The Serving Layer is the waiter who combines the overnight broth with the fast-cooked ingredients to hand the customer a complete, up-to-the-second meal.

How the 3 Layers Work Together

When new data enters the system (like clickstreams, sensor readings, or transactions), it immediately splits into two pipelines:

(Below is a detailed architectural diagram of this flow)


graph LR
    subgraph Data Sources
        DS[New Data]
    end

    subgraph Lambda Architecture
        subgraph Batch Layer
            BL1[(Master Dataset)] --> BL2[Batch Processing]
        end
        
        subgraph Speed Layer
            SL[Stream Processing]
        end
        
        subgraph Serving Layer
            SV1[(Batch Views)]
            SV2[(Real-time Views)]
        end
    end
    
    DS --> BL1
    DS --> SL
    
    BL2 --> SV1
    SL --> SV2
    
    SV1 --> Q[Query]
    SV2 --> Q

1. Batch Layer (Historical Accuracy)

The batch layer is responsible for permanently storing all incoming raw data in an immutable append-only format, and periodically reprocessing this entire master dataset (for example, every 6 or 12 hours). Its greatest strength is delivering absolute historical accuracy and handling highly complex calculations across years of data. Because it operates on a complete dataset, it automatically corrects any errors or missing data from the fast-tracked streams. However, this thoroughness comes at a cost: it suffers from high latency and takes a long time to compute. Popular tools for this layer include Apache Spark, Hadoop, and AWS EMR.

2. Speed Layer (Real-Time Recency)

To compensate for the high latency of the batch layer, the speed layer processes live streaming data that hasn't yet been included in the most recent batch run—often spanning just the last few hours or even seconds. Its primary advantage is providing near-instant results with incredibly low latency. To achieve this speed, it intentionally sacrifices historical completeness and complex re-computations. This layer typically utilizes streaming engines like Apache Flink, Apache Storm, or Apache Kafka Streams.

3. Serving Layer (The Merge)

The serving layer acts as the bridge connecting the previous two layers to the end user. When a user queries the system, the serving layer responds by seamlessly blending the pre-calculated, highly accurate historical data from the batch layer with the instant, real-time data from the speed layer. As a result, users receive a complete, up-to-the-minute view of the data without heavily taxing or overwhelming the underlying databases.


Summary: Pros & Cons

Advantages Disadvantages
Best of both worlds: Delivers both real-time speed and historical accuracy. High complexity: Requires maintaining two separate codebases/pipelines (one batch, one streaming).
Fault tolerant: If the speed layer makes a mistake, the next batch run overwrites and corrects it. Higher cost: Requires running double the infrastructure.

Real-World Example: Black Friday E-Commerce Dashboard

Imagine you are managing an online store on Black Friday. The CEO wants a live dashboard showing total revenue generated today up to the current minute.

Since millions of orders are coming in every second, querying a database for all orders from midnight to right now would crash the database. Here is how Lambda Architecture solves this:

Step-by-Step Scenario (Time: 2:15 PM)

1. Incoming Data Stream

Every time a customer clicks "Buy", an event is fired (e.g., Order #9822 - $50). This event is immediately sent to both the Batch Layer and the Speed Layer simultaneously.


graph LR
    Order["Live Order: $50"] --> Batch["Batch Layer
(S3 / Hadoop)"] Order --> Speed["Speed Layer
(Kafka + Flink)"] Batch --> Job["Hourly Heavy Job"] Speed --> Counter["Real-Time Counter"]
2. The Batch Layer (12:00 AM – 2:00 PM)

Every hour on the hour—for instance, at 2:00 PM—a heavy background job utilizing frameworks like Spark or Hadoop processes all raw orders accumulated from midnight up to that point. This rigorous process calculates the exact, fully verified historical revenue, which in this scenario totals $12,500,000. This snapshot is then permanently stored as a fixed view (e.g., batch_view_2pm).

3. The Speed Layer (2:00 PM – 2:15 PM)

Because the last batch job finished precisely at 2:00 PM, any orders placed afterward fall into a processing gap. The speed layer, powered by real-time tools like Flink or Kafka Streams, solves this by keeping a lightweight, running total in memory strictly for those new orders. In our example, it actively tracks the fast delta for the last 15 minutes, amounting to $85,000.

4. The Serving Layer (Answering the CEO at 2:15 PM)

When the CEO refreshes the dashboard at exactly 2:15 PM, the serving layer performs a simple on-the-fly addition. It takes the verified Batch Result of $12,500,000 and adds the Speed Result of $85,000, instantly rendering the fully accurate Total Revenue of $12,585,000.


What happens when the clock hits 3:00 PM?

As the clock strikes 3:00 PM, the system resets its cycle. The Batch Layer triggers a new comprehensive job to process all data from 12:00 AM to 3:00 PM. Once complete, the Serving Layer seamlessly swaps to this newly generated batch_view_3pm. Simultaneously, the Speed Layer discards its old state and resets its memory counter to zero, ready to begin tracking only the new orders that arrive from 3:00 PM onwards.

If a network glitch caused the speed layer to miss an order between 2:00 PM and 3:00 PM, it doesn't matter long-term—the 3:00 PM batch run will re-process the raw immutable log and automatically correct the error.

(Note: Because maintaining two separate codebases in Lambda is difficult, many modern systems use Kappa Architecture, which processes everything through a single streaming engine.)


2. Kappa Architecture

The Kappa Architecture, proposed by Jay Kreps, aims to simplify the Lambda Architecture by entirely eliminating the Batch Layer. It relies on a single technology stack—stream processing—to handle both real-time and historical data.

In a Kappa architecture, all data flows through a single stream processing engine (like Apache Kafka combined with Apache Flink or Spark Streaming). Historical data can be reprocessed by simply replaying the stream.


graph LR
    subgraph Data Sources
        DS[New Data]
    end

    subgraph Kappa Architecture
        subgraph Streaming System
            Log[(Immutable Log
e.g., Kafka)]
        end
        
        subgraph Stream Processing
            SP[Real-time Processing]
        end
        
        subgraph Serving Layer
            SV[(Serving Views)]
        end
    end
    
    DS --> Log
    Log --> SP
    SP --> SV
    SV --> Q[Query]

Pros and Cons of Kappa

Pros: A single codebase and infrastructure to maintain. Simplified operational overhead and easier to manage data logic since everything is a stream.

Cons: Requires a highly robust and scalable event streaming platform (like Kafka) capable of storing massive amounts of historical data. Handling extremely complex historical data joins can sometimes be more challenging in a pure streaming paradigm compared to batch.


Why Kappa Seems Simple on Paper but Is Not Used by Many

While Kappa Architecture sounds elegant on paper—a single codebase, no batch layer, and processing everything as a stream—it comes with significant real-world engineering and financial trade-offs.

Many organizations choose not to adopt pure Kappa for several key reasons:

1. Historical Replays (Backfilling) Are Expensive and Slow

In Kappa, if you change a business calculation or fix a bug in your code, you must re-process historical data by replaying past events through the streaming engine.

  • Resource Inefficiency: Streaming engines (like Flink or Spark Streaming) process data record-by-record or micro-batch by micro-batch. Doing this over years of petabyte-scale historical data consumes vast CPU and RAM resources compared to a optimized batch engine like Spark SQL, which reads parquet files with column pruning and vectorized scans.
  • Time to Replay: Replaying 3 years of event streams can take days or weeks, making backfilling painfully slow.

2. High Cost of Log Storage

Kappa relies on storing raw immutable event logs indefinitely (or for long retention periods) in platforms like Apache Kafka or Pulsar so they can be replayed.

  • Streaming log storage (NVMe/SSD drives attached to brokers) is significantly more expensive than standard cloud object storage (AWS S3, Google Cloud Storage, Azure Blob).
  • Even with Kafka's Tiered Storage, managing index lookups and streaming IOPS across historical petabytes introduces extra cost and operational complexity.

3. Stateful Stream Processing is Difficult to Operate

Managing state in a streaming engine (e.g., maintaining long-term state on RocksDB in Apache Flink) is notoriously complex:

  • State Size Explosion: If you need to join events across a wide time window (e.g., a 30-day user attribution window), the streaming engine must keep 30 days of uncommitted state in memory/disk.
  • Checkpointing Failure: As state grows into multi-terabyte sizes, distributed checkpointing becomes slow and prone to timeouts during node failures.

4. Not All Analytical Workloads Fit Streaming Logic

Stream processing is built around incremental event processing. However, many business requirements are inherently batch-oriented:

  • Complex Ad-hoc SQL Queries: Aggregating data across arbitrary dimensions (e.g., "Find all users who bought items in category X after visiting page Y across 5 years") requires scanning full datasets, which doesn't fit stream topology.
  • Machine Learning Training: Training deep learning or ML models requires bulk matrix operations over static datasets, not streaming pipelines.

5. The Rise of the "Lakehouse" Alternative

Instead of choosing between Lambda and Kappa, the industry has shifted toward the Data Lakehouse (using table formats like Apache Iceberg, Delta Lake, or Apache Hudi):

  • Unified Storage: Data is stored cheaply in open Parquet format on S3/GCS.
  • Unified Compute: Apache Spark or DuckDB can read the exact same Iceberg table incrementally as a stream (for low latency) or as a batch job (for fast backfills and heavy analytics) without keeping expensive streaming clusters running 24/7.

Summary

Kappa Architecture is ideal for event-driven microservices, real-time alerting, and low-latency dashboards where historical backfills are rare or datasets are small. However, for large enterprise data platforms handling heavy analytical scans, petabyte-scale historical reprocessing, and complex SQL reporting, the operational complexity and infrastructure cost of pure Kappa make it impractical.


Related Guides:
← PreviousPrinciples of Data Engineering ArchitectureNext →OLTP vs OLAP: Architecture