Kinesis Data Streams Overview
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
Lesson: Amazon Kinesis Data Streams Overview
Introduction: The Necessity of Real-Time Data Ingestion
In the modern digital landscape, data is rarely static. Businesses no longer rely solely on batch processing—where data is collected, stored, and analyzed in large chunks at the end of the day. Instead, the demand for immediate insights has pushed organizations toward streaming architectures. Whether it is tracking user behavior on a website, monitoring telemetry from industrial IoT sensors, or processing financial transactions for fraud detection, the ability to ingest and react to data as it is generated is a critical competitive advantage.
Amazon Kinesis Data Streams (KDS) serves as the backbone for this real-time data movement. It is a managed service that allows you to collect and process large streams of data records in real-time. By acting as a buffer between data producers (the sources) and data consumers (the processing engines), Kinesis enables your architecture to decouple components, handle spikes in traffic, and ensure that data is processed reliably without losing information.
Understanding how to effectively implement Kinesis Data Streams is essential for any data engineer or architect. It is not just about moving bytes from point A to point B; it is about building a system that is durable, scalable, and capable of handling the unpredictable nature of live data feeds. Throughout this lesson, we will explore the core mechanics of Kinesis, how to integrate it into your workflows, and the best practices required to maintain a healthy production environment.
The Core Architecture of Kinesis Data Streams
To master Kinesis, you must first understand the fundamental building blocks that comprise a data stream. A Kinesis Data Stream is essentially a sequence of data records that are organized into shards. When you create a stream, you are essentially defining a capacity unit that can handle a specific volume of data.
Shards: The Unit of Scale
A shard is the base throughput unit of an Amazon Kinesis data stream. Each shard provides a fixed capacity: 1 MB/sec of data input (ingress) and 2 MB/sec of data output (egress). Additionally, a single shard supports up to 1,000 records per second for writes and 5 transactions per second for reads. If your application needs to handle more data, you increase the number of shards, which scales your throughput linearly.
Data Records
A data record is the unit of data stored in the stream. It consists of three primary components:
- Partition Key: This is used to segregate and route data to specific shards within the stream. If you have multiple shards, Kinesis uses the partition key to determine which shard a record belongs to.
- Sequence Number: A unique identifier assigned by Kinesis to each record upon ingestion. This number is useful for tracking the order of data and ensuring that no records are missed during processing.
- Data Blob: This is the actual data payload, which can be up to 1 MB in size. It is treated as an opaque sequence of bytes by Kinesis, meaning the service does not care about the internal structure of your data.
Callout: Stream vs. Queue While Kinesis Data Streams and Amazon SQS (Simple Queue Service) are both messaging services, they serve different purposes. SQS is a point-to-point queue where a message is consumed once and then deleted. Kinesis is a log-based, multi-consumer stream where data is persisted for a retention period (default 24 hours up to 365 days), allowing multiple independent applications to consume the same data simultaneously.
Setting Up Your First Data Stream
Before writing code, you must provision the infrastructure. While this can be done through the AWS Management Console, it is best practice to use Infrastructure as Code (IaC) tools like Terraform or AWS CloudFormation for production environments.
Step-by-Step Provisioning
- Define the Stream Name: Choose a name that is unique within your AWS account and region.
- Set the Shard Count: Estimate your expected throughput. If you expect 5 MB/sec of ingress, you need at least 5 shards.
- Retention Period: Decide how long the data should remain in the stream. If you need to replay data in case of a consumer failure, you might increase this from the default 24 hours to several days.
- Encryption: Enable server-side encryption to ensure that data is protected at rest.
Once the stream is active, you can begin sending data to it using the AWS SDKs.
Producing Data: The Ingestion Layer
The "Producer" is any application that pushes data into the Kinesis stream. Common producers include web servers, mobile applications, IoT devices, or even other AWS services like CloudWatch Logs or AWS IoT Core.
Example: Python Producer
Using the boto3 library, you can easily push data to a stream. The most important aspect of producing data is the partition key. If you use a random partition key, your data will be distributed evenly across all shards. If you use a specific ID (like a user_id), all data for that user will land in the same shard, which is critical if you need to maintain strict ordering for that specific user.
import boto3
import json
import random
kinesis_client = boto3.client('kinesis', region_name='us-east-1')
def send_data(stream_name, user_id, action):
payload = {
'user_id': user_id,
'action': action,
'timestamp': '2023-10-27T10:00:00Z'
}
# The partition key ensures data for the same user goes to the same shard
response = kinesis_client.put_record(
StreamName=stream_name,
Data=json.dumps(payload),
PartitionKey=str(user_id)
)
return response
# Usage
send_data('my-app-stream', 12345, 'click')
In the example above, the PartitionKey is set to the user_id. This ensures that all actions performed by user_id: 12345 are written to the same shard, preserving the order of operations for that user. This is a common requirement for session-based analytics.
Tip: Use Batching When dealing with high-volume producers, calling
put_recordfor every single event is inefficient due to network latency. Useput_recordsinstead, which allows you to send up to 500 records (or 5 MB) in a single API call. This significantly reduces the overhead on your producer application and improves throughput.
Consuming Data: The Processing Layer
Data consumers are responsible for reading data from the stream and performing some action, such as storing it in a database, transforming it, or triggering an alert.
The Kinesis Client Library (KCL)
The Kinesis Client Library (KCL) is the recommended way to consume data. It abstracts away much of the complexity, such as handling shard leases, load balancing across consumers, and checkpointing. When you run multiple instances of a consumer application, the KCL automatically distributes the shards among them. If one instance fails, the KCL redistributes the shards to the remaining healthy instances.
Example: Simple Consumer Logic
If you are building a lightweight consumer, you might use the basic get_records API, though this is usually reserved for simple use cases or debugging.
# Simplified view of consuming data
shard_iterator = kinesis_client.get_shard_iterator(
StreamName='my-app-stream',
ShardId='shardId-000000000000',
ShardIteratorType='LATEST'
)['ShardIterator']
while True:
response = kinesis_client.get_records(ShardIterator=shard_iterator, Limit=100)
records = response['Records']
for record in records:
data = json.loads(record['Data'])
print(f"Processing: {data}")
shard_iterator = response['NextShardIterator']
Best Practices for Production
Building a system that runs reliably 24/7 requires more than just functional code. You must account for failures, throughput fluctuations, and data integrity.
1. Handling Throughput Spikes
Kinesis Data Streams is not automatically elastic in terms of shard count. If you suddenly experience a 10x increase in traffic, your producers will start receiving ProvisionedThroughputExceededException errors. You must implement a strategy to monitor your metrics (specifically IncomingBytes and IncomingRecords) and either manually update the shard count or use the UpdateShardCount API to scale dynamically.
2. Checkpointing
Checkpointing is the process of tracking the position of the last successfully processed record in a shard. If your consumer crashes, it needs to know where to resume. Using the KCL handles this automatically by storing sequence numbers in a DynamoDB table. If you are writing a custom consumer, you must implement your own checkpointing mechanism to avoid processing the same data twice or losing data upon restart.
3. Monitoring with CloudWatch
Every Kinesis stream should be monitored via Amazon CloudWatch. Key metrics to track include:
- ReadProvisionedThroughputExceeded: Indicates that your consumers are not reading fast enough.
- WriteProvisionedThroughputExceeded: Indicates that your producers are sending more data than the shards can handle.
- GetRecords.IteratorAgeMilliseconds: This is the most important metric. It measures how far behind the consumer is from the "head" of the stream. If this number is growing, your consumers are falling behind in real-time processing.
4. Data Serialization
Always use a structured format like JSON, Avro, or Protocol Buffers. While Kinesis accepts binary blobs, serializing your data ensures that your downstream consumers (like Lambda or EMR) can parse the data without guessing the format. Using a schema registry (like AWS Glue Schema Registry) is an excellent way to enforce data quality and ensure producers and consumers stay in sync.
Warning: Iterator Age If your
GetRecords.IteratorAgeMillisecondsgrows to match your retention period, you are on the verge of losing data. Kinesis will delete data once it exceeds the retention period, regardless of whether it has been processed. Always set up CloudWatch alarms for this metric to trigger when the lag exceeds a safe threshold.
Common Pitfalls and How to Avoid Them
Even experienced engineers can run into issues with Kinesis. Being aware of these common mistakes will save you significant troubleshooting time.
Hot Shards
A "hot shard" occurs when data is not distributed evenly across your shards. This usually happens when the PartitionKey is poorly chosen (e.g., using a key that has a high frequency of identical values). If one shard receives 80% of the traffic, you will hit the 1 MB/sec limit on that shard, even if your total stream capacity is underutilized.
- Solution: Ensure your partition keys have high cardinality. If you are using
user_id, make sure there are thousands of unique users rather than just a few.
Silent Failures in Producers
If a producer fails to send a record, it might not always crash the application. If you aren't checking the response object from put_record, you might be losing data without knowing it.
- Solution: Always wrap your producer calls in error handling logic. Log failures to a dead-letter queue (DLQ) or an error log so you can retry or investigate later.
Consumer Backpressure
Sometimes, the consumer is simply too slow. Perhaps it is performing complex calculations or waiting on a slow database write.
- Solution: If your consumer cannot keep up, you have two options: increase the number of shards (to allow for more parallel consumers) or optimize the consumer's processing logic. Batching your database writes or using asynchronous I/O can often resolve consumer bottlenecks.
Comparison: Kinesis Data Streams vs. Kinesis Data Firehose
It is common to confuse Kinesis Data Streams with Kinesis Data Firehose. While they both handle data, they serve different architectural roles.
| Feature | Kinesis Data Streams | Kinesis Data Firehose |
|---|---|---|
| Purpose | Real-time streaming/processing | Near real-time loading to storage |
| Latency | Sub-second (milliseconds) | 60 seconds to several minutes |
| Consumer | Custom (Lambda, EC2, EMR) | Managed (S3, Redshift, OpenSearch) |
| Management | You manage shards/scaling | Fully managed, auto-scaling |
| Retention | 24 hours to 365 days | None (data is transient) |
Use Kinesis Data Streams when you need to perform complex, real-time analytics or when you have multiple consumers that need to read the same stream independently. Use Kinesis Data Firehose when your goal is simply to land data into an S3 bucket or a data warehouse for later analysis.
Step-by-Step: Scaling Your Stream
If you find that your traffic has increased and your current shard count is no longer sufficient, you need to scale.
- Check Current Capacity: Review the
IncomingBytesmetric in CloudWatch. If it is consistently near the 1 MB/sec per shard limit, it is time to scale. - Calculate New Shards: If you need 5 MB/sec and currently have 2 shards, you need to scale up to at least 5 shards.
- Execute Scale: Use the AWS CLI to update the shard count.
aws kinesis update-shard-count \ --stream-name my-app-stream \ --target-shard-count 5 \ --scaling-type UNIFORM_SCALING - Verify: Once the operation completes, your new shards will be available. Note that this process takes a few minutes, so plan for it during off-peak hours if possible.
Advanced Concepts: Enhanced Fan-Out
For high-performance applications, standard Kinesis consumption might introduce too much latency because all consumers share the same 2 MB/sec read throughput per shard. If you have multiple applications reading from the same stream, they might compete for throughput, leading to increased latency.
Enhanced Fan-Out (EFO) provides each consumer with its own dedicated 2 MB/sec throughput. This is achieved by using HTTP/2 protocol to push records from Kinesis to the consumer. This is highly recommended when you have multiple, mission-critical consumers reading the same data stream, as it eliminates the "noisy neighbor" problem where one consumer's high throughput needs starve another.
Integrating with AWS Lambda
One of the most powerful features of Kinesis is its native integration with AWS Lambda. Lambda can act as a consumer, automatically polling the stream and invoking your code for every batch of records.
Lambda Configuration
When you map a Lambda function to a Kinesis stream, you define a BatchSize (how many records to send to the function at once) and a BatchWindow (the maximum amount of time to wait to fill the batch). This allows you to balance cost and latency.
- Tip: If your processing logic is fast, keep the
BatchSizesmall to keep latency low. If you are doing heavy processing, increase theBatchSizeto get better efficiency out of your Lambda execution.
Key Takeaways for Success
- Shards are the Capacity Unit: Always design your stream based on your peak throughput requirements. Remember that each shard provides 1 MB/sec ingress and 2 MB/sec egress.
- Partition Keys Matter: Use high-cardinality keys to distribute data evenly and prevent "hot shards." If ordering is critical, ensure related records share the same partition key.
- Monitor Iterator Age: This is the definitive metric for "real-time" health. If your iterator age is high, your system is not truly processing in real-time.
- Implement Robust Error Handling: Producers and consumers will eventually fail. Ensure your architecture includes retries, dead-letter queues, or checkpointing to maintain data integrity.
- Choose the Right Tool: Don't use Data Streams if you only need to land data in S3; use Kinesis Data Firehose to save yourself the management overhead.
- Scale Proactively: Use CloudWatch alarms to detect when you are approaching your shard capacity and scale before you experience throughput exceptions.
- Security First: Always enable server-side encryption and use IAM roles with the principle of least privilege to control who can read from or write to your streams.
By adhering to these principles, you will be able to build data pipelines that are not only performant but also resilient enough to handle the demands of modern, real-time enterprise applications. Kinesis Data Streams is a powerful tool, and when used with the right architectural patterns, it becomes the reliable foundation of your data-driven strategy.
Continue the course
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons