Skip to main content
Articles/#apache-spark/spark-stateful-aggregations-mapgroupswithstate
Series: Data Engineering & Spark Mastery•Part 17 of 19
Scenario Article

Stateful Aggregations in Spark Structured Streaming: mapGroupsWithState

When Fraud Detection Breaks Every Window Assumption

Abstract Algorithms•Apr 19, 2026
💡 Executive Summary

mapGroupsWithState gives each streaming key its own mutable state object, persisted in a fault-tolerant state store that checkpoints to object storage on every micro-batch.

🎯 System Scenario & Requirements

System Goal

mapGroupsWithState gives each streaming key its own mutable state object, persisted in a fault-tolerant state store that checkpoints to object storage on every micro-batch.

Actors & Components

  • Application Workers
  • Volatile Memory Tier
  • Persistent Disk Tier
  • Worker Process
  • In-Memory Cache
  • Primary Database

Functional Requirements

  • TLDR: mapGroupsWithState gives each streaming key its own mutable state object, persisted in a fault-tolerant state store that checkpoints to object storage on every micro-batch.
  • Where window aggregations assume fixed time boundaries, mapGroupsWithState lets you model arbitrary state machines — fraud sessions, IoT device lifecycles, complex event patterns — with full control over state transitio…
  • The cost is operational: state can grow unboundedly if not explicitly expired, the RocksDB state store requires careful memory tuning, and checkpoint size grows with both key cardinality and state object size.

Constraints & Assumptions

  • Constraints are derived from the rebuilt scenario stages.

⚡ Execution Stages & Decision Trace

1

Stage 1 — The mapGroupsWithState API: Keys, State, Timeouts, and the GroupState Contract

Action / Decision:

The mapGroupsWithState operator lives on a grouped streaming Dataset.

Component Behavior:

Its type signature defines four type parameters: the key type K , the event value type V , the state type S , and the output type U .

Observable Output: Your state-transition function receives three arguments on each call: - The key — the value of the grouping expression for this key group - An iterator of new events — all events for this key that arrived in the current…
Read Full Stage in Deep Dive ↓
📖

Deep Dive

Detailed Architectural Analysis

Scenario context

mapGroupsWithState gives each streaming key its own mutable state object, persisted in a fault-tolerant state store that checkpoints to object storage on every micro-batch. Where window aggregations assume fixed time boundaries, mapGroupsWithState lets you model arbitrary state machines — fraud sessions, IoT device lifecycles, complex event patterns — with full control over state transitions, multi-row output, a…

This walkthrough focuses on When Fraud Detection Breaks Every Window Assumption.

Before making a design choice, clarify:

  • A real-time fraud detection team at a payments company builds a streaming pipeline on Spark Structured Streaming.
  • Their goal: flag users who make more than five high-value transactions within a single "session," where a session ends either when the user goes thirty minutes without activity or when the suspicious pattern is confirme…
  • On paper, this looks like a window aggregation problem.

Concepts in play: spark-data-engineering, caching, consistency-replication, python-concurrency-nogil

Stage 1 — The mapGroupsWithState API: Keys, State, Timeouts, and the GroupState Contract

  • The mapGroupsWithState operator lives on a grouped streaming Dataset.
  • Its type signature defines four type parameters: the key type K , the event value type V , the state type S , and the output type U .
  • Your state-transition function receives three arguments on each call: - The key — the value of the grouping expression for this key group - An iterator of new events — all events for this key that arrived in the current…
  • Each method maps directly to a state store operation: Timeout semantics control when Spark calls your state function for a key even when no new events arrived for it in the current batch.

Observable outcome: Each method maps directly to a state store operation: Timeout semantics control when Spark calls your state function for a key even when no new events arrived for it in the current batch.

Stage 2 — Deep Dive: How Spark Persists and Manages Per-Key State Internally

  • The Internals of Spark's State Store Architecture Every mapGroupsWithState operator is backed by a state store — a versioned, partitioned key-value store managed by Spark's executor processes.
  • Understanding the state store architecture is a prerequisite for reliable production operation.
  • Partitioning : State is partitioned by key hash, using the same partition count as the shuffle for the grouped stream.
  • A stream configured with spark.sql.shuffle.partitions = 200 maintains 200 independent state store instances, one per executor task.
<checkpointLocation>/
  commits/                 # batch commit log
    0                      # batch 0 committed
    1                      # batch 1 committed
  offsets/                 # source offsets per batch
    0
    1
  state/
    0/                     # operator index 0
      0/                   # partition 0
        1.delta            # changes in batch 1
        2.delta            # changes in batch 2
        10.snapshot        # full state snapshot at batch 10
        11.delta           # changes since snapshot
      1/                   # partition 1
        ...
  metadata
f : (K, Iterator[V], GroupState[S]) → U

Observable outcome: A stream configured with spark.sql.shuffle.partitions = 200 maintains 200 independent state store instances, one per executor task.

Stage 3 — Designing a Fraud Detection State Machine for Streaming Sessions

  • A production fraud detection pipeline using mapGroupsWithState should be designed as an explicit finite state machine before a single line of state function code is written.
  • The state machine defines the complete set of states, every permitted transition, and every timeout behavior.
  • The mapGroupsWithState function then mechanically implements that specification.
  • Consider a per-user transaction fraud detector with five lifecycle stages: - Inactive : No state is stored.
stateDiagram-v2
    [*] --> Inactive
    Inactive --> Watching : first_transaction_received
    Watching --> Suspicious : velocity_threshold_exceeded
    Watching --> Inactive : session_timeout_30m
    Suspicious --> Flagged : pattern_confirmed
    Suspicious --> Watching : anomaly_cleared
    Flagged --> [*] : case_closed
    Inactive --> [*] : key_expired

Observable outcome: Consider a per-user transaction fraud detector with five lifecycle stages: - Inactive : No state is stored.

Stage 4 — The mapGroupsWithState Execution Flow Across a Micro-Batch

  • Each micro-batch in a stateful streaming query follows a fixed sequence of operations.
  • Understanding this sequence reveals where time is spent, which steps dominate latency, and where configuration changes have the most leverage.
  • The diagram below traces the complete lifecycle of a single micro-batch, from trigger to offset commit.
  • The steps from "Load state" through "Expire timed-out keys" all execute per-partition in parallel across executors.
graph TD
    A[Micro-batch trigger fires] --> B[Read new events from Kafka source partitions]
    B --> C[Group events by key using hash partitioning]
    C --> D[Load per-key state from state store partition]
    D --> E[Apply state function for each key group]
    E --> F{Emit output?}
    F -->|Yes| G[Write output rows to downstream sink]
    F -->|No output| H[State updated without emitting rows]
    G --> I[Write updated state back to state store]
    H --> I
    I --> J[Checkpoint state store delta to object store]
    J --> K[Evaluate timed-out keys and invoke state function with hasTimedOut]
    K --> L[Remove expired keys from state store]
    L --> M[Commit batch offset to Kafka consumer group log]

Observable outcome: The steps from "Load state" through "Expire timed-out keys" all execute per-partition in parallel across executors.

Stage 5 — Where Per-Key Stateful Streaming Appears in Production Systems

  • User session tracking for personalization : E-commerce and media platforms track active user sessions — pages visited, items viewed, funnel stage, time-on-page — for real-time recommendation and A/B test attribution.
  • Session boundaries are defined by idle gaps between events, not clock intervals.
  • Netflix's real-time personalization layer uses stateful streaming to track viewing session progress and drive content recommendations within an active viewing session.
  • The session state object holds a compact summary of the session's events; it is emitted on session close for downstream model features.

Observable outcome: The session state object holds a compact summary of the session's events; it is emitted on session close for downstream model features.

Stage 6 — Choosing the Right Stateful API for Your Streaming Use Case

  • This decision table maps use case complexity, state size, and output cardinality to the appropriate API.
  • The column headers reflect the three key axes that determine which tool is correct.
  • The central decision axis is whether your state transitions require more than a running accumulator.
  • If the answer is yes, reach for one of the mapGroupsWithState variants.

Observable outcome: If the answer is yes, reach for one of the mapGroupsWithState variants.

End-to-end outcome

After working through the stages, you should be able to explain:

  • Always bound your state object size.
  • The most common production incident with mapGroupsWithState is unbounded state growth.
  • TLDR: mapGroupsWithState gives each streaming key its own mutable state object, persisted in a fault-tolerant state store and checkpointed to object storage on every micro-batch.
  • Model your state as an explicit finite state machine before writing the function.

Alternatives considered

mapGroupsWithState vs. Alternatives: Where Each API Breaks Down

Choosing the right stateful operator is a prerequisite for both correctness and performance.

Failure and degraded modes

The source does not isolate a separate failure mode. Limits that matter for the scenario are called out in the stage decisions above.

Share this case study

Discuss architecture trade-offs and lessons with your team.

Share:XLinkedInReddit