Cloud Architecture

Building Scalable Data Pipelines with Kinesis, Glue, & Redshift

Learn to build robust, scalable data pipelines on AWS using Kinesis for real-time ingestion, Glue for serverless ETL, and Redshift for powerful analytics.

Khader Vali October 3, 2026 16 min read

Building Scalable Data Pipelines on AWS with Kinesis, Glue, and Redshift

As a senior software engineer, I’ve seen firsthand how crucial efficient data handling is for modern businesses. In today’s data-driven world, the ability to ingest, process, and analyze vast amounts of data in near real-time is not just an advantage—it’s a necessity. From understanding customer behavior to optimizing operational efficiency, timely insights derived from data are the fuel for innovation and competitive edge.

However, building robust and scalable data pipelines can be a daunting task. You need to consider data volume, velocity, variety, and veracity, all while ensuring cost-effectiveness, security, and maintainability. This is where cloud platforms like Amazon Web Services (AWS) shine, offering a suite of managed services designed to simplify these complexities.

In this comprehensive guide, we’ll dive deep into constructing a powerful, serverless, and highly scalable data pipeline on AWS using three core services: Amazon Kinesis for real-time data ingestion, AWS Glue for serverless Extract, Transform, Load (ETL) operations, and Amazon Redshift for petabyte-scale data warehousing and analytics. We’ll explore their individual strengths, how they integrate seamlessly, and walk through a real-world scenario with code examples and architectural considerations.

The Modern Data Landscape and the Imperative for Robust Pipelines

The digital age has ushered in an era of unprecedented data generation. Every click, sensor reading, transaction, and interaction contributes to an ever-growing ocean of information. This “big data” phenomenon is often characterized by the three Vs:

  • Volume: The sheer quantity of data, often measured in terabytes or petabytes.
  • Velocity: The speed at which data is generated and needs to be processed – from batch to real-time streaming.
  • Variety: The diverse formats and types of data, including structured, semi-structured, and unstructured.

Beyond these, two more Vs are often added:

  • Veracity: The quality and trustworthiness of the data.
  • Value: The business insights that can be extracted from the data.

Traditional data warehousing solutions, designed primarily for structured data processed in nightly batches, often struggle to keep up with the velocity and variety of modern data. Businesses now demand near real-time insights to react swiftly to market changes, personalize user experiences, detect fraud, and monitor systems proactively. This necessitates data pipelines that can:

  • Ingest data continuously from various sources.
  • Process data on the fly, applying transformations and enrichments.
  • Store data efficiently in formats optimized for analytics.
  • Load data reliably into analytical data stores.
  • Scale elastically to handle fluctuating data loads.
  • Be cost-effective, paying only for what’s consumed.

AWS provides a compelling ecosystem to meet these demands. Its managed services abstract away much of the operational burden, allowing engineers to focus on data logic rather than infrastructure management. Let’s introduce the key players in our pipeline.

Core AWS Services for Our Data Pipeline

Our pipeline leverages three powerful AWS services, each specializing in a different stage of the data journey:

  1. Amazon Kinesis: For high-throughput, real-time data ingestion.
  2. AWS Glue: For serverless data cataloging and ETL.
  3. Amazon Redshift: For petabyte-scale data warehousing and analytics.

1. Amazon Kinesis: The Real-time Data Backbone

Amazon Kinesis is a fully managed service for real-time processing of large streams of data. It’s designed to handle massive throughput from hundreds of thousands of data sources, making it ideal for applications like log aggregation, clickstream analysis, IoT telemetry, and financial transaction processing. Kinesis offers several capabilities, but for our pipeline, we’ll primarily focus on Kinesis Data Streams and Kinesis Data Firehose.

Kinesis Data Streams

Kinesis Data Streams is the foundational component for real-time data streaming. It acts as a durable, fault-tolerant buffer for incoming data. Data is organized into shards, which are the base throughput units of a stream. Each shard provides a capacity of 1MB/second of ingress and 2MB/second of egress, supporting up to 1,000 records per second. You scale a stream by increasing the number of shards.

Key concepts:

  • Producers: Applications that send data to a Kinesis Data Stream (e.g., web servers, IoT devices, Lambda functions).
  • Consumers: Applications that read and process data from a Kinesis Data Stream (e.g., Kinesis Data Analytics, Lambda, Kinesis Client Library applications).
  • Retention: Data in a Kinesis Data Stream is durable for 24 hours by default, extendable up to 365 days.

Kinesis Data Streams is best suited when you need custom real-time processing, multiple consumers reading the same stream, or if you require longer data retention for re-processing.

Kinesis Data Firehose

Kinesis Data Firehose is an ETL service that reliably captures, transforms, and loads streaming data into data lakes, data stores, and analytics services. It’s designed to be simpler and more direct than Data Streams when your primary goal is to deliver data to a destination like Amazon S3, Amazon Redshift, Splunk, or Elasticsearch. Firehose automatically scales to match the throughput of your data and requires no administration.

Firehose can perform basic transformations (e.g., converting record format from JSON to Parquet/ORC, compressing data) and even invoke AWS Lambda functions for custom data transformations before delivery. It also buffers data and batches it to reduce the number of objects written to S3, which is crucial for optimizing downstream processing.

For our pipeline, Firehose will serve as the bridge between the high-velocity Kinesis Data Stream and our S3 data lake landing zone, providing a managed, scalable way to buffer and deliver raw data.

Building Scalable Data Pipelines with Kinesis, Glue, & Redshift
Generated Image

2. AWS Glue: The Serverless ETL and Data Catalog Maestro

AWS Glue is a fully managed, serverless data integration service that makes it easy to discover, prepare, and combine data for analytics, machine learning, and application development. It’s a cornerstone for building data lakes and ETL pipelines on AWS, eliminating the need to provision or manage servers.

Glue Data Catalog

At the heart of Glue is the Data Catalog, a central metadata repository. It stores schema information, table definitions, and location of your data across various data stores (S3, RDS, Redshift, etc.). Think of it as a persistent metadata store that makes your data discoverable and queryable by other AWS services like Athena, Redshift Spectrum, and EMR.

Glue Crawlers

Glue Crawlers automatically connect to your data stores, infer the schema and data types, and then create or update table definitions in the Glue Data Catalog. This feature is incredibly powerful for dealing with semi-structured data in S3, as it saves you from manually defining schemas. Crawlers can also detect partitions in your data, which is essential for optimizing query performance.

Glue ETL Jobs

Glue ETL jobs are serverless Apache Spark or Python Shell scripts that perform transformations, cleansing, and enrichment of your data. You can develop these jobs using PySpark or Scala. Glue manages the underlying Spark environment, including provisioning resources, scaling, and monitoring. This means you only pay for the compute resources consumed during the job execution.

Glue ETL jobs can read data from various sources (S3, relational databases, Kinesis, Kafka), apply complex transformations, and write the processed data to different destinations. This flexibility makes Glue an ideal choice for transforming raw, incoming data into a clean, structured, and analytics-ready format.

3. Amazon Redshift: The Petabyte-Scale Data Warehouse

Amazon Redshift is a fully managed, petabyte-scale data warehouse service in the cloud. It’s designed for analytical workloads, allowing you to run complex analytical queries against vast datasets and achieve high performance. Redshift uses columnar storage, data compression, and massively parallel processing (MPP) to deliver fast query results.

Columnar Storage and MPP

  • Columnar Storage: Instead of storing data row by row, Redshift stores data column by column. This is highly efficient for analytical queries that often read a subset of columns from a large table, as it reduces the amount of data that needs to be read from disk.
  • Massively Parallel Processing (MPP): Redshift distributes data and query processing across multiple compute nodes. When you run a query, it’s executed in parallel by all nodes, significantly speeding up complex aggregations and joins.

Use Cases

Redshift is perfect for:

  • Business Intelligence (BI) and reporting.
  • Customer behavior analysis.
  • Operational analytics.
  • Financial reporting.

Redshift Spectrum

An important capability of Redshift is Redshift Spectrum. It allows you to run SQL queries against exabytes of data stored in Amazon S3 directly, without needing to load the data into Redshift tables. This is incredibly useful for querying large historical datasets in your S3 data lake while still leveraging Redshift’s query optimizer and familiar SQL interface.

For our pipeline, Redshift will be the final destination for our processed, analytics-ready data, serving as the backbone for downstream BI tools and dashboards.

Architecting the Pipeline: Kinesis Data Stream -> Firehose -> S3 -> Glue -> Redshift

Let’s outline the architecture for our robust, near real-time data pipeline. This setup ensures data is ingested efficiently, transformed reliably, and loaded into an analytical data warehouse for insights.

High-Level Architecture Overview (Diagram in Words)

Imagine a flow of data, starting from its origin and moving through several stages:

  1. Data Producers: Applications (e.g., web servers, mobile apps, IoT devices) generate events (e.g., clickstream data, logs, sensor readings).
  2. Kinesis Data Stream: Producers send these events to a Kinesis Data Stream, which acts as a highly scalable, durable buffer for raw, real-time data.
  3. Kinesis Data Firehose: A Kinesis Data Firehose delivery stream is configured to consume data from the Kinesis Data Stream. Firehose buffers the data, optionally performs basic transformations (e.g., format conversion), and delivers it to an Amazon S3 bucket.
  4. S3 Raw Data Lake (Landing Zone): The Firehose stream lands the raw, incoming data (e.g., JSON files) into a designated S3 bucket, often referred to as the “raw” or “landing” zone of our data lake.
  5. AWS Glue Crawler: A Glue Crawler periodically scans the S3 raw data bucket, infers the schema of the incoming data, and registers table definitions in the AWS Glue Data Catalog.
  6. AWS Glue Data Catalog: This central metadata repository stores the schema and location information for both raw and processed data in S3.
  7. AWS Glue ETL Job: A scheduled (or triggered) Glue ETL job reads the raw data from S3 (using the schema from the Data Catalog), performs complex transformations, cleansing, and enrichment. It then writes the transformed, cleaned data (e.g., in Parquet format, partitioned) to another S3 bucket.
  8. S3 Processed/Curated Data Lake: This S3 bucket holds the structured, high-quality data ready for analysis. This can also serve as a source for other services like Athena or Redshift Spectrum.
  9. Amazon Redshift: The processed data from the S3 processed bucket is loaded into Amazon Redshift tables. This loading can be orchestrated by the Glue ETL job directly or by a separate process using Redshift’s highly efficient COPY command.
  10. Analytics & BI Tools: Finally, tools like Amazon QuickSight, Tableau, or custom dashboards connect to Redshift to query the data and generate insights.

This architecture provides both real-time ingestion capabilities (Kinesis) and a robust batch processing layer (Glue) to prepare data for powerful analytical queries in Redshift, all while leveraging S3 as a cost-effective and scalable data lake storage.

Step-by-Step Implementation Details

Step 1: Data Ingestion with Amazon Kinesis Data Streams

First, we need a Kinesis Data Stream to capture our events. Let’s assume we’re collecting user clickstream data from a web application.

Setup Kinesis Data Stream:

Navigate to the Kinesis console, choose “Data Streams”, and create a new stream. Give it a name like my-clickstream-data-stream and specify the number of shards. Start with a small number (e.g., 1 or 2) and scale up as needed. For testing, 1 shard is usually sufficient.

Producers: Sending Data to Kinesis

Data producers can be anything from a server-side application to an IoT device. For demonstration, let’s use a simple Python script to simulate sending clickstream events.

Before running, ensure you have the boto3 library installed (pip install boto3) and your AWS credentials configured.


import boto3
import json
import time
import random
from datetime import datetime

# Initialize Kinesis client
kinesis_client = boto3.client('kinesis', region_name='us-east-1') # Replace with your region

STREAM_NAME = 'my-clickstream-data-stream'

def generate_click_event():
    """Generates a sample clickstream event."""
    user_id = f"user_{random.randint(1, 1000)}"
    session_id = f"sess_{random.randint(10000, 99999)}"
    page_id = f"page_{random.randint(1, 50)}"
    event_type = random.choice(['page_view', 'add_to_cart', 'purchase', 'search'])
    timestamp = datetime.now().isoformat()
    
    event = {
        'timestamp': timestamp,
        'user_id': user_id,
        'session_id': session_id,
        'page_id': page_id,
        'event_type': event_type,
        'product_id': f"prod_{random.randint(1, 200)}" if event_type in ['add_to_cart', 'purchase'] else None,
        'quantity': random.randint(1, 5) if event_type in ['add_to_cart', 'purchase'] else None,
        'ip_address': f"{random.randint(1, 255)}.{random.randint(1, 255)}.{random.randint(1, 255)}.{random.randint(1, 255)}"
    }
    return event

def send_to_kinesis(event):
    """Sends a single event to Kinesis Data Stream."""
    try:
        response = kinesis_client.put_record(
            StreamName=STREAM_NAME,
            Data=json.dumps(event) + '\n', # Add newline for easier processing later
            PartitionKey=event['user_id'] # Use user_id for consistent partitioning
        )
        print(f"Sent record: {event['event_type']} for user {event['user_id']}. Sequence Number: {response['SequenceNumber']}")
    except Exception as e:
        print(f"Error sending record: {e}")

if __name__ == "__main__":
    print(f"Sending simulated clickstream events to Kinesis stream: {STREAM_NAME}")
    try:
        while True:
            event = generate_click_event()
            send_to_kinesis(event)
            time.sleep(random.uniform(0.1, 0.5)) # Simulate varying event frequency
    except KeyboardInterrupt:
        print("Stopped sending events.")

This script generates sample JSON events and sends them to the Kinesis Data Stream. The PartitionKey is crucial; it determines which shard the record goes into. Using `user_id` ensures that all events for a particular user go to the same shard, which can be beneficial for ordered processing if needed.

Step 2: Buffering and Initial Landing in S3 with Kinesis Data Firehose

Now, we’ll configure a Kinesis Data Firehose to consume from our my-clickstream-data-stream and deliver the raw JSON data to an S3 bucket.

Setup S3 Bucket:

Create an S3 bucket, for example, my-data-lake-raw-clickstream-data. Inside this bucket, Firehose will create a prefix structure like `YYYY/MM/DD/HH`.

Setup Kinesis Data Firehose:

Navigate to the Kinesis console, choose “Delivery Streams”, and create a new delivery stream.

  • Source: Select “Kinesis Data Stream” and choose your my-clickstream-data-stream.
  • Record Transformation: For this initial raw landing, we’ll select “Disabled” to deliver raw data as is. For more advanced scenarios, you could enable Lambda transformation here.
  • Convert record format: Select “Disabled”. We want the raw JSON.
  • Destination: Select “Amazon S3”.
  • S3 Destination Settings: Choose your S3 bucket (my-data-lake-raw-clickstream-data) and optionally a prefix (e.g., raw/clickstream/).
  • Buffer Hints: Configure buffering. For testing, you might set a low buffer size (e.g., 1MB) and buffer interval (e.g., 60 seconds) to see data land faster. In production, larger buffers (e.g., 128MB or 300 seconds) are common to optimize S3 object size for downstream processing.
  • Error Logging: Enable CloudWatch logging for errors.
  • IAM Role: Create a new IAM role or choose an existing one that grants Firehose permissions to read from Kinesis Data Stream and write to S3.

Once the Firehose is created, start your Python producer script. Within a few minutes (depending on your buffer settings), you should see compressed JSON files appearing in your S3 raw bucket.

Step 3: Data Cataloging with AWS Glue Crawlers

Before we can transform our data, we need to understand its structure. AWS Glue Crawlers will automatically infer the schema from the JSON files in our S3 raw bucket and register it in the Glue Data Catalog.

Setup Glue Crawler:

Navigate to the AWS Glue console, go to “Crawlers”, and add a new crawler.

  • Crawler name: e.g., clickstream-raw-crawler.
  • Data stores: Add an S3 data store. Specify the path to your raw clickstream data (e.g., s3://my-data-lake-raw-clickstream-data/raw/clickstream/).
  • IAM Role: Create a new IAM role or use an existing one that has permissions to read from your S3 raw bucket and write to the Glue Data Catalog.
  • Schedule: Set a schedule. For a near real-time pipeline, you might run it hourly or every few hours. For initial setup, choose “Run on demand”.
  • Output: Choose an existing database or create a new one (e.g., raw_data_db) in the Glue Data Catalog where the table definition will be stored.

Once created, run the crawler. After it completes, navigate to “Tables” in the Glue Data Catalog. You should see a new table (e.g., clickstream) with inferred columns like timestamp, user_id, page_id, etc. If your data has nested structures, Glue will try to flatten them or create structs.

Step 4: ETL with AWS Glue Jobs

Now that our raw data is cataloged, we can use AWS Glue ETL jobs to clean, transform, and enrich it. We’ll convert the raw JSON into a more efficient columnar format (Parquet), clean up some fields, and write it to a “processed” S3 bucket.

Setup S3 Processed Bucket:

Create another S3 bucket for processed data, e.g., my-data-lake-processed-clickstream-data. We’ll partition this data by year, month, and day for optimized querying.

Create Glue ETL Job:

Navigate to the AWS Glue console, go to “ETL jobs”, and add a new job. Choose “Spark E.g. Apache Spark” and “Python” as the language. Select the IAM role used by the crawler (ensure it also has write permissions to the processed S3 bucket).

Here’s a sample PySpark script for a Glue ETL job. It reads the raw JSON, performs some basic transformations, and writes the output as Parquet files, partitioned by date.


import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from pyspark.sql.functions import col, from_unixtime, to_timestamp, year, month, dayofmonth, hour, lit

# @params: [JOB_NAME]
args = getResolvedOptions(sys.argv, ['JOB_NAME'])

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

# Define input and output paths
# Make sure your Glue Data Catalog table 'clickstream' is in 'raw_data_db'
source_database = "raw_data_db"
source_table = "clickstream" # This is the table created by the crawler
output_path = "s3://my-data-lake-processed-clickstream-data/processed/clickstream/"

# Read raw data from Glue Data Catalog
# The Glue Data Catalog table points to the S3 raw bucket
datasource0 = glueContext.create_dynamic_frame.from_catalog(
database=source_database,
table_name=source_table,
transformation_ctx="datasource0"
)

# Convert DynamicFrame to Spark DataFrame for easier manipulation
df = datasource0.toDF()

# --- Data Transformations ---
# 1. Cast timestamp to proper timestamp type and extract date components
# Assuming timestamp is ISO 8601 string
df_transformed = df.withColumn("event_timestamp", to_timestamp(col("timestamp"))) \
.withColumn("event_year", year(col("event_timestamp"))) \
.withColumn("event_month", month(col("event_timestamp"))) \
.withColumn("event_day", dayofmonth(col("event_timestamp")))

# 2. Select and reorder columns, potentially rename for clarity
df_final = df_transformed.select

Written by

Khader Vali

Senior Software Engineer specializing in cloud architecture, real-time systems, and enterprise-scale applications.

Share this article

Related Articles

Building Scalable Data Pipelines on AWS: Kinesis, Glue, Redshift

Sep 03, 2026 · 15 min read

Mastering Cloud Security: IAM, Encryption, and Zero Trust

Sep 15, 2026 · 17 min read

Edge Computing: Architectures, Patterns & Use Cases

Aug 16, 2026 · 15 min read