This project implements 4 types of windowing strategies using Apache Kafka Streams and Spring Boot.
Windowing allows you to partition and aggregate events over time, which is essential for real-time analytics, fraud detection, and time-based aggregations.
- Java: 17
- Spring Boot: 3.5.10
- Spring Kafka: Latest (managed by Spring Boot parent)
- Kafka Streams: Latest (managed by Spring Boot parent)
- OpenApi: 2.5.0 (for API documentation)
- Build Tool: Maven
- Java 17+
- Docker & Docker Compose (for Kafka)
- Maven 3.6+
docker-compose up -dmvn clean install
mvn spring-boot:runWindowing divides an infinite stream of events into finite chunks (windows) so that you can aggregate data over specific time periods. Each window has a defined start and end time, and events are assigned to windows based on their timestamps.
- Non-overlapping, fixed-size windows that partition the data stream into consecutive intervals.
- Once a window closes, it won't accept new events.
- Windows do NOT overlap.
- Perfect for discrete time-based reporting.
spring:
window:
type: tumblingFor a 10-second tumbling window:
- Window 1: [0s - 10s]
- Window 2: [10s - 20s]
- Window 3: [20s - 30s]
.windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofSeconds(10)))- ✅ Hourly/daily sales reports
- ✅ Session-based analytics
- ✅ Batch processing with strict time boundaries
- ✅ Non-overlapping aggregations
- Overlapping, fixed-size windows that advance by a specified interval (hop interval).
- Multiple windows can contain the same event.
- Useful when you need overlapping time periods.
- Provides smoother trends by reducing gaps.
spring:
window:
type: hoppingFor a 10-second window with 4-second hop:
- Window 1: [0s - 10s]
- Window 2: [4s - 14s]
- Window 3: [8s - 18s]
- Window 4: [12s - 22s]
(Each window overlaps by 6 seconds with the next)
.windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofSeconds(10))
.advanceBy(Duration.ofSeconds(4)))- ✅ Moving averages
- ✅ Fraud detection with overlapping time ranges
- ✅ Smoothed real-time metrics
- ✅ Sliding average calculations
- Overlapping windows that accommodate events falling within a specific time difference.
- A new window is created for each event.
- Windows overlap completely based on event timestamps.
- More memory-intensive than other window types.
- Best for finding events that occur within a time range.
spring:
window:
type: slidingFor a 10-second sliding window:
- Each event starts its own window that lasts 10 seconds
- All events within 10 seconds of each other are grouped together
.windowedBy(SlidingWindows.ofTimeDifferenceWithNoGrace(Duration.ofSeconds(10)))- ✅ Correlation detection
- ✅ Finding events within a time range of each other
- ✅ Real-time anomaly detection
- ✅ Grouping related events by time proximity
⚠️ Use with caution due to higher memory consumption
- Dynamic windows defined by periods of inactivity (gaps).
- A session window starts when an event arrives and ends when there's a gap of inactivity longer than the configured duration.
- Window boundaries are not fixed in time.
- Perfect for capturing user sessions or activity bursts.
- Each unique key can have multiple sessions.
spring:
window:
type: sessionFor a 10-second inactivity gap:
- Event at 0s: Session starts [0s...]
- Event at 3s: Added to same session [0s...]
- Event at 8s: Added to same session [0s...]
- No event for 10+ seconds: Session closes
- Event at 22s: New session starts [22s...]
.windowedBy(SessionWindows.with(Duration.ofSeconds(10)))- ✅ User session tracking
- ✅ Activity burst detection
- ✅ User behavior analysis
- ✅ Grouping related transactions by inactivity gaps
- ✅ Detecting when users go idle
| Feature | Tumbling | Hopping | Sliding | Session |
|---|---|---|---|---|
| Overlapping | ❌ No | ✅ Yes | ✅ Yes | ❌ No* |
| Fixed Size | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No |
| Fixed Time | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No |
| Complexity | Low | Medium | High | Medium |
| Memory Usage | Low | Medium | High | Medium |
| Event Overlap | None | Controlled | Complete | By inactivity |
*Session windows overlap conceptually per key, but time boundaries are data-driven, not fixed.
Edit application.yml and set the desired window type:
spring:
window:
type: tumbling # or hopping, sliding, sessiontumbling→ Tumbling Window (default)hopping→ Hopping Windowsliding→ Sliding Windowsession→ Session Window
Only the configured bean will be instantiated at startup. The others will be ignored via @ConditionalOnProperty.
The application:
- Reads stock trade events from the
stocksKafka topic - Groups events by
userID - Applies the selected windowing strategy
- Counts trades per window
- Detects fraud alerts (> 3 trades in a window)
- Outputs results to
user-stock-countstopic
All windowing strategies implement the same fraud detection logic:
if (count > 3) {
logger.warn("🚨 [WINDOW_TYPE] ALERT: User={} made {} stocks trade!", user, count);
}When a user makes more than 3 stock trades within a single window, an alert is triggered and logged.
Tumbling Window | 🧾 User=john_doe | Count=4 | Window=[2024-01-15 10:00:00 - 2024-01-15 10:00:10]
🚨 TUMBLING WINDOWING STOCK ALERT: User=john_doe made 4 stocks trade within 10 seconds!
✅ Conditional Bean Loading - Only active bean is instantiated based on configuration
✅ Window Suppression - Results only emitted when windows close
✅ State Store - Materialized state store for windowed aggregations
✅ Graceful Closure - Proper handling of window boundaries
✅ Logging - Detailed logging with window timing information
✅ Flexible Serdes - Appropriate serializers for each window type
| Window Type | Memory | CPU | Latency | Best For |
|---|---|---|---|---|
| Tumbling | ⭐⭐ Low | ⭐⭐ Low | ⭐⭐⭐ High | Batch reports, fixed intervals |
| Hopping | ⭐⭐⭐ Medium | ⭐⭐⭐ Medium | ⭐⭐ Medium | Moving averages, smoothed metrics |
| Sliding | ⭐⭐⭐⭐⭐ High | ⭐⭐⭐⭐ High | ⭐ Low | Precise time-range detection |
| Session | ⭐⭐⭐ Medium | ⭐⭐⭐ Medium | ⭐⭐ Medium | User sessions, activity tracking |
server:
port: 9191
spring:
application:
name: sample-spring-boot-kstreams
kafka:
bootstrap-servers: localhost:9092
streams:
application-id: stocks-streams
state-dir: target/kafka-stream-logs
window:
type: tumbling # Change this to switch windowing types
logging:
pattern:
console: "%green(%d{HH:mm:ss.SSS}) %blue(%-5level) %red([%thread]) %yellow(%logger{15}) - %msg%n"src/main/java/com/kodebytes/acasado/
├── controller/
│ └── StockWindoingController.java # REST endpoint to publish stocks
├── events/
│ └── Stocks.java # Domain model
│ └── Item.java # Domain model
├── streams/
│ └── StockWindowingStream.java # Window: tumbling, hopping, sliding, session
├── serdes/
│ └── StocksSerde.java # Custom serialization
└── config/
└── KafkaConfig.java # Kafka configuration
└── OpenApiConfig.java # OpenApi configuration
To test each windowing strategy:
- Start Kafka & Zookeeper
- Create topics:
kafka-topics --create --topic stocks --bootstrap-server localhost:9092 kafka-topics --create --topic user-stock-counts --bootstrap-server localhost:9092
- Update
application.ymlwith desired window type - Start the application
- Send stock events to the
stockstopic - Monitor alerts in application logs
✅ Expected behavior - Use @ConditionalOnProperty to activate only one bean
- Check if count > 3 for events in a single window
- Verify events are arriving in the
stockstopic - Check window timing aligns with your event timestamps
- Consider switching from Sliding Window to Hopping Window
- Reduce window size if possible
- Monitor state store growth
This implementation demonstrates all major windowing strategies in Kafka Streams, allowing you to choose the best approach for your use case. Each window type has distinct characteristics, and the choice depends on your specific requirements for time boundaries, data overlap, and performance constraints.
Start with Tumbling Windows for simplicity, then experiment with others based on your use case!
This project is for educational purposes.