How to Build Scalable Real-Time Data Systems

Set latency SLOs, pick Lambda or Kappa, partition by entity, manage state, and monitor lag to build scalable real‑time pipelines.

How to Build Scalable Real-Time Data Systems

If I had to boil this down to one point, it’s this: I don’t start with tools. I start with targets. For most teams, that means setting latency goals like under 250 ms, 250 ms to 5 seconds, or 5 to 60 seconds, then sizing for traffic such as 15,000 events per second with spikes up to 75,000, while keeping uptime around 99.9% to 99.99%.

Here’s the short version:

  • I define success with p95 and p99 latency, not averages
  • I match the design to the workload, like fraud scoring, IoT streams, dashboards, or CDC
  • I pick Lambda if batch and stream both matter, or Kappa if one stream path is enough
  • I scale with partitions, state control, idempotency, and replay
  • I watch lag, errors, backpressure, and cost per 1,000 events
  • I scale consumers from lag and backlog, not just CPU

In other words: a scalable real-time system is just a pipeline that can ingest, process, store, serve, and recover under load without letting latency drift, costs run wild, or failures pile up.

What follows is my condensed take on the article, with the main build choices, tradeoffs, and rules kept simple.

Building the Next Generation of Real Time Data Pipelines: Data Mesh and Streaming SQL at Netflix

Netflix

Choose the Right Architecture and Core Stack

Lambda vs. Kappa Architecture: Real-Time Data System Comparison

Lambda vs. Kappa Architecture: Real-Time Data System Comparison

Once you’ve set latency and throughput targets, the next call is the architecture pattern. That choice affects almost everything after it: how data gets split, how failures are handled, and how much day-to-day ops work your team has to carry over time.

Lambda vs. Kappa Architecture: When to Use Each

Lambda architecture, introduced by Nathan Marz, uses a batch layer for accurate historical computation, a speed layer for low-latency views, and a serving layer that combines both. It makes sense for teams that already have mature batch systems and need accurate historical views and near-real-time views. A good example is a U.S. fintech that needs GAAP-compliant nightly ledger reconciliation alongside real-time balance updates.

Kappa architecture removes the batch layer and sends all data through one streaming pipeline. If you need to reprocess data, you replay the event log through updated code. This setup works well for event-driven use cases like fraud detection, user behavior analytics, ops monitoring, AI-driven personalization, and autonomous agents, where a steady live stream matters more than a reconciled batch view.

Dimension Lambda Kappa
Complexity High - two codebases, a merge layer, and separate ops Lower - one pipeline, but strong state and versioning practices are still required
Latency Speed layer is near-real-time; batch layer is hourly or nightly Consistent low latency for both live and reprocessed data
Reprocessing Batch layer handles it; backfills can be slow and resource-intensive Replay the event log through updated code
Operational overhead High - teams monitor and troubleshoot two stacks plus serving Lower overall, but backpressure and state management still need discipline

Pick here carefully. This is the fork in the road that shapes how you partition data, manage state, and deliver results to downstream systems.

A Reference Stack for Ingest, Process, and Serve

For ingestion, start with a durable event log that fits your deployment model and ordering needs.

Tool Best Fit
Apache Kafka On-premises or multi-cloud; strong ordering guarantees
Amazon Kinesis Fully managed ingestion on AWS
Google Pub/Sub Fully managed ingestion on GCP

For stream processing, the right framework depends on your SLAs and what your team can run well in practice.

Framework Scalability Latency State Handling Deployment Model
Apache Flink Horizontal cluster scaling Millisecond latency Robust keyed state, checkpoints, savepoints, exactly-once Dedicated cluster (Kubernetes, YARN)
Spark Structured Streaming Horizontal cluster scaling 100–500 ms micro-batch mapGroupsWithState; more batch-oriented conceptually Spark cluster (shared with ETL/ML)
Apache Beam Depends on runner Runner-dependent Abstracted state and timers Multi-cloud via chosen runner
Kafka Streams Scales with app instances Low with tuning Embedded state stores such as RocksDB Embedded in microservices (for example, Spring Boot)

For serving, choose the data store based on how people or systems will query it.

Store Best Fit
Cassandra, DynamoDB, Bigtable High-write key-value workloads
ClickHouse, Apache Pinot Real-time OLAP and sub-second analytical queries
Redis Caches and fast lookups such as session state for chatbots

When to Work with NAITIVE AI Consulting Agency

For AI automation workloads, architecture choices also affect agent state, voice latency, and recovery after failure. That matters a lot with autonomous agents, phone and voice agents, and business process automation, where even small delays can pile up fast.

NAITIVE AI Consulting Agency helps design and manage real-time systems for AI automation, autonomous agents, phone/voice agents, and business process automation.

Design a Horizontally Scalable Real-Time Pipeline

With the architecture set, the next job is making ingestion, processing, and recovery grow together. That’s where pipeline design stops being theory and starts showing up in throughput, latency, and failover behavior. For organizations struggling with these complexities, NAITIVE AI consulting provides specialized architectural guidance.

Ingestion and Partitioning for Parallel Throughput

Partitioning is what gives you parallel throughput. More partitions mean more consumers can work at the same time. For example, at about 200 MB/s per partition, hitting 10 GB/s calls for roughly 50 partitions.

A common place to start is 2–4 partitions per consumer core, and one production setup begins at 20 partitions and moves to 40 after event rates pass 50,000 events per second.

But partition count isn’t the main thing. The partition key matters more.

Use a high-cardinality key like customer_id, account_id, or device_id. That keeps events for the same entity in one partition, which preserves ordering for that entity. If the key is skewed, you get hot partitions: one shard gets slammed while others barely do any work.

When skew can’t be avoided, add a sharding suffix such as customer_id + random_shard. That spreads traffic out while still keeping ordering acceptable at the shard level.

You also want to size partitions for where the system is going, not just where it is now. Plan for 12–18 months of growth. Repartitioning a live topic can be painful, so it’s better to leave room early. On the producer side, tune batching with batch.size and linger.ms. On the consumer side, control fetch behavior and in-flight work with max.poll.interval.ms and in-flight limits.

Once partitioning is balanced, the next pressure point is state. If state grows without limits, scale starts to hit memory walls.

Stateful Stream Processing and Low-Latency Storage

Tools like Apache Flink and Kafka Streams keep per-key state across events. That state powers windows, joins, and aggregations.

Different window types fit different jobs:

  • Tumbling windows for fixed time buckets
  • Sliding windows for overlapping views
  • Session windows for bursty user activity

For stream-stream joins, set retention and watermarks so state stays bounded and late events are still handled correctly.

Effectively-once processing comes from putting a few parts together: idempotent producers, transactional writes, and checkpoints that save operator state and offsets at the same time. Flink’s distributed snapshot algorithm handles this across all partitions and operators in one coordinated pass.

Checkpoint timing is a tradeoff. Shorter intervals cut recovery time, but they add runtime overhead. Longer intervals lower that overhead, but they increase the amount of data that may need replay after a failure. In practice, checkpoint intervals should line up with your internal RTO and RPO targets.

Processed data then lands in stores and caches built for fast downstream reads. The best choice depends on the query pattern.

Storage Option Typical Read Latency Best Write Pattern Scaling Model Operational Complexity
Redis Sub-millisecond to a few ms Hot-key reads, session data Horizontal sharding, clustering Medium - requires eviction policy and HA setup
DynamoDB / Cassandra Single-digit to tens of ms High write throughput, key-based lookups Horizontal partitioning, auto-scaling Medium to High - partition design and capacity tuning
ClickHouse / BigQuery Tens to hundreds of ms Batched or micro-batched analytical writes Distributed MPP, elastic scale Medium - query tuning and cost control
PostgreSQL with replicas Low-ms reads from replicas Transactional writes, complex queries Vertical scale plus read replicas Medium to High - replication and failover management
Elasticsearch / OpenSearch Low to tens of ms Text search, log analytics Sharded indices, cluster scaling High - index lifecycle and cluster tuning

A simple rule of thumb helps here: use Redis for hot materialized views, DynamoDB for high-write key-value access, and ClickHouse for analytical scans.

After state and storage are set, the next step is dealing with duplicates, retries, and the mess that failures tend to leave behind.

Idempotency, Retries, and Failure Recovery

You should assume at-least-once delivery. In plain terms, duplicates will happen. Design for them from day one.

Give every message a unique event ID. For external actions, use idempotency keys. For internal writes, use UPSERTs or dedup logs.

At the broker level, Kafka producers should use acks=all and enable.idempotence=true. That gives you idempotent retries during production. For retry policy, use exponential backoff with a cap. If failures keep happening, send the event to a DLQ along with the attempt count and error type.

For recovery, restore stateful processors from the last successful checkpoint and replay from that offset. Then test failover across U.S. regions using live traffic so you can verify actual RTO and RPO behavior, not just what looks good on paper.

Deploy, Monitor, and Scale in Production

Once recovery is set, production work moves to three day-to-day concerns: safe releases, clear visibility, and scaling that matches load.

Provision Infrastructure and Deploy Safely

Define Kafka, Kubernetes, storage, networking, and IAM in version-controlled IaC. Keep development, staging, and production separate - best case, each lives in its own account or project with its own networking, clusters, data stores, and IAM boundaries. That separation helps keep test traffic and half-finished changes from spilling into production and hurting SLAs.

For deployments, use the rollout method that fits the level of risk. Rolling updates are fine for lower-risk changes. Blue-green deployments make rollback fast when downtime needs to stay close to zero. Canary releases work especially well for stream processor updates: send 1%–5% of traffic to the new version, watch lag and error rates, and then increase traffic step by step.

Don’t size production from gut feel. Size it from load tests. For the first release, add 30%–50% headroom. Then check that buffer against p95 latency and consumer lag, not rough estimates.

Monitor Lag, Latency, Errors, and Backpressure

Real-time observability comes down to three things: metrics, logs, and traces. Metrics tell you that something is off. Logs help explain why. Traces show where the slowdown or failure happened.

For metrics, Prometheus with Grafana is a common setup. Watch consumer lag by partition and consumer group, p95 and p99 end-to-end latency, throughput by topic, error rates, DLQ volume, and resource saturation across CPU, memory, disk I/O, and network throughput. Buffer use and backlog age can warn you about backpressure before lag jumps.

Centralize logs with structured fields and correlation IDs so a failed record can be tied back to the event that triggered it. Add distributed tracing with a tool like Jaeger or OpenTelemetry for span-level visibility across ingestion, processing, and serving layers.

Metric / Focus Observability Category Typical Dashboard View
Consumer lag per partition Metrics (time series) Line chart by consumer group and topic
p95 / p99 end-to-end latency Metrics + Traces Latency percentile chart plus trace waterfall
Error rate, DLQ volume Metrics + Logs Error count by service, DLQ messages over time
CPU, memory, disk I/O Metrics Node/pod resource utilization heatmap with alerts
Backpressure signals Metrics Service-specific backpressure graphs and thresholds
Throughput (events/sec) Metrics Events per second by topic and service
Slow queries / API spans Traces + Logs Trace explorer with span durations and correlated logs

Set alerts on lag growth rate, not only on the raw lag number. Lag often traces back to hot partitions or slow state stores, so break it out by topic, partition, and consumer group. If your system has a 2-minute action window, sustained lag past 60–90 seconds should trigger immediate investigation. A jump in DLQ volume right after a deployment often means a logic bug or a schema mismatch, so it helps to have a triage process that reviews DLQ samples every day.

Those same signals should also drive scaling decisions.

Autoscaling and Capacity Planning

CPU-based autoscaling is fine for simple stateless services. For stream consumers, it’s usually better to scale on lag or backlog.

Tools like KEDA can scale consumer pods straight from Kafka lag or queue depth, which ties replica count to actual backlog and SLA risk. In the processing layer, custom-metric policies with Prometheus or Datadog can scale from backpressure signals, events per second, or p95 latency - whichever lines up best with your SLO.

Autoscaling Strategy Responsiveness Stability Implementation Complexity
CPU / Memory Based Medium High Low - standard Kubernetes HPA
Lag-Based (e.g., KEDA + Kafka) High Medium Moderate - requires metric exporter setup
Custom Metric (queue depth, p95 latency) High Moderate High - custom Prometheus queries or Datadog integration

To keep scaling from bouncing up and down, set cool-down periods of 5–10 minutes between scaling decisions. Define minimum and maximum replica counts, and use different thresholds for scale-out and scale-in. Scale out when CPU goes above 60% to 70% or when lag crosses your backlog threshold. Scale in only when use falls below 30% to 40% and stays there.

Scale the bottleneck layer, not the entire stack. Find the hotspot - maybe a few partitions or one service pulling far more resources than the rest - and then decide whether you need more nodes, larger nodes, or code changes. It also helps to pair resource metrics with a cost-per-1,000-events figure. That gives budget owners a plain way to compare scaling out against tuning processing logic before adding more monthly spend. Use those numbers to keep the system inside SLA as load and partition behavior shift.

Apply the System to Automation Use Cases and Review the Build Path

Support AI Automation, Dashboards, and Real-Time Decisions

Once the pipeline is stable in production, the next step is simple: line it up with the workflows it needs to handle. At that point, the big question isn't whether the system works. It's whether it works fast enough for the job.

That matters because the last few design calls shape the outcome. The right setup can keep automation moving in milliseconds. The wrong one can slow the whole thing down.

A fraud system reached sub-10 ms p99 latency and cut fraudulent transactions by 83%. A supply-chain platform handling 3 million shipments a day reduced alert time from hours to minutes.

The same pipeline patterns show up across fraud, agents, IoT, dashboards, and contact centers. But they don't all use the exact same stack.

Automation Use Case Architecture Pattern Storage Choice
Fraud Detection Event-Driven Streaming Redis or another low-latency key-value store
AI Automation / Autonomous Agents Event-Driven (EDA) Vector database, online feature store
IoT / Equipment Monitoring Kappa (stream-centric) Time-series database
Logistics Visibility Kappa + Real-Time OLAP Time-series database or OLAP store
Live Dashboards Kafka or Pub/Sub, stream processing, metrics pipeline Prometheus or another metrics store
Contact Center Workflows Event-Driven (EDA) Document database, vector database

For AI automation, event streams feed an online feature store, get scored in-line, and then route actions right away. Voice agents and autonomous agents can query a vector database in real time. At the same time, drift and error monitors can trigger retraining or rollback before small issues turn into bigger ones.

Conclusion: Key Design Rules for Scalable Real-Time Systems

These use cases all point back to the same build rules, no matter the domain.

Keep six rules in play:

  • Set SLOs first
  • Choose Lambda or Kappa early
  • Partition by the business entity
  • Build idempotency and recovery in from day one
  • Treat observability as a core feature
  • Scale from measured load, not estimates

NAITIVE AI Consulting Agency helps teams design, build, and manage AI automation, autonomous agents, voice agents, and business process automation when end-to-end ownership matters.

FAQs

How do I choose between Lambda and Kappa?

Choose based on whether you want a simpler setup or need batch processing for specific jobs.

Lambda keeps batch and streaming in separate layers. That can help when you need a dependable historical record and real-time updates at the same time.

Kappa runs on a single streaming layer. That makes the system simpler, cuts duplicate code, and keeps AI systems working from the latest data.

What is a good partition key for streaming data?

The provided information does not include guidance on how to choose a partition key for streaming data.

If you need architecture guidance or help with streaming setup, NAITIVE AI Consulting Agency can help design real-time data solutions for your infrastructure.

When should I scale consumers based on lag?

It depends on the workload.

For background agent task queues, scale based on queue depth. Tools like KEDA work well here, with sources such as Kafka or Redis Streams, because queue depth shows the backlog directly.

For latency-sensitive interactive agents, scale based on p95 latency with Horizontal Pod Autoscalers and custom metrics. If p95 latency goes above your target, add replicas to keep performance steady.

Related Blog Posts