
Clickstream systems at scale are not about logging more events. They are about preserving raw truth, surviving consumer bugs, and keeping operational dashboards fast without turning search into the primary datastore. A media or ad-tech platform must ingest millions of click, impression, and engagement events per minute, support near-real-time dashboards, and preserve raw data for replay, ML feature generation, and compliance analytics.
TL;DR: Use Kinesis Data Streams for ingestion, Firehose plus S3 for durable storage, Glue and Athena for analytics, and OpenSearch only for curated operational search slices.
Why Naive Solutions Break — AWS clickstream analytics
Sending every event directly to a database or search cluster causes write amplification, indexing bottlenecks, and runaway costs. Tight coupling between producers and consumers makes schema changes dangerous, and without durable raw storage, bad consumers corrupt the only copy of the truth.
Architecture Overview
Use API Gateway or edge collectors to receive events, buffer them through Kinesis Data Streams, process them with Lambda or Kinesis consumers, store immutable raw data in S3, expose ad hoc analytics through Athena and Glue Catalog, and index curated subsets into OpenSearch for operational dashboards.
Architecture Diagram

Service-by-Service Breakdown
API Gateway: Ingest endpoint for browser, mobile, or backend event producers.Kinesis Data Streams: Durable high-throughput stream for ordered partitioned ingestion.Lambda: Lightweight transformations, enrichment, filtering, and metric aggregation.EventBridge: Routes curated high-level domain events to internal systems.Kinesis Data Firehose: Delivers batched data to S3 and optionally OpenSearch with buffering and compression.S3: Raw immutable event lake with partitioned prefixes.AWS Glue Data Catalog: Schema registry for Athena queries and downstream ETL jobs.Athena: Serverless SQL for investigations, cohort analysis, and cost-efficient replay validation.OpenSearch: Near-real-time dashboards for traffic, errors, campaign performance, and anomaly triage.CloudWatch and X-Ray: Stream lag, consumer failures, batch retry visibility, and trace correlation from ingestion to storage.
Request Lifecycle and Data Flow
- Producers send batched events to API Gateway.
- Events are partitioned into Kinesis shards by user, tenant, session, or campaign key.
- Lambda consumers validate schemas, enrich records, and discard malformed events to a dead-letter path.
- Firehose batches the stream into compressed files in S3 with time-based partitioning.
- Glue updates metadata so Athena can query the latest partitions.
- Selected operational fields are indexed into OpenSearch for low-latency dashboards.
- Important derived domain events are pushed to EventBridge for personalization or alerting systems.
Production Code Patterns
Kinesis producer payload with partition discipline
import boto3, json, hashlib
kinesis = boto3.client('kinesis')
def put_event(stream_name, tenant_id, session_id, payload):
partition_key = hashlib.sha256(f"{tenant_id}:{session_id}".encode()).hexdigest()[:32]
kinesis.put_record(
StreamName=stream_name,
PartitionKey=partition_key,
Data=json.dumps(payload).encode('utf-8'),
)
Athena table over partitioned Parquet clickstream data
CREATE EXTERNAL TABLE IF NOT EXISTS analytics.clickstream_events (
event_id string,
tenant_id string,
user_id string,
session_id string,
event_type string,
ts timestamp,
attributes map<string,string>
)
PARTITIONED BY (dt string, event_family string)
STORED AS PARQUET
LOCATION 's3://cheatcoders-clickstream/curated/events/';
Scaling Strategy
- Increase Kinesis shard count or adopt on-demand capacity for bursty traffic.
- Partition keys must balance order guarantees with hotspot avoidance.
- Scale consumers based on iterator age and processing lag.
- Keep raw S3 writes append-only and perform downstream aggregation asynchronously.
- Reserve OpenSearch for query-heavy slices instead of every raw event field.
Cost Optimization Techniques
- Compress Firehose output with Parquet or ORC for Athena efficiency.
- Partition S3 by date, tenant, or event type to reduce Athena scanned bytes.
- Filter and sample low-value events before indexing into OpenSearch.
- Tune Kinesis retention and consumer model to match replay requirements.
- Move cold raw data to cheaper S3 storage classes using lifecycle rules.
Security Best Practices
- Sign ingestion requests and enforce per-producer auth at API Gateway.
- Encrypt streams, buckets, and search domains with KMS.
- Use bucket policies that restrict access to specific roles and VPC endpoints.
- Mask or tokenize PII before events reach broad analytics surfaces.
- Use fine-grained OpenSearch access controls for operations and analysts.
Failure Handling and Resilience
- Persist raw events first so all downstream consumers are recoverable.
- Monitor iterator age to detect lag before data becomes stale.
- Route poison events to quarantine buckets or DLQs.
- Rebuild downstream projections by replaying from S3 or Kinesis retention.
- Run multi-AZ OpenSearch and Kinesis consumers for service-level resilience.
Trade-offs and Alternatives
Kinesis is strong for ordered streaming and predictable AWS-native integrations, but it requires shard planning for sustained traffic. SQS can be simpler for independent jobs, while MSK is better if Kafka ecosystem compatibility is mandatory.
Real-World Use Case
A Netflix-style personalization and engagement analytics platform can use this design to track video starts, completion rates, device metrics, and recommendation feedback loops.
Key Interview Insights
- Separate the immutable source of truth from derived indexes.
- Discuss why OpenSearch is a serving layer, not the canonical event store.
- Explain partition-key design and consumer lag as first-class scaling concerns.
- Show how replayability changes operational confidence and incident recovery.
Recommended resources
Free Weekly Newsletter
🚀 Don’t Miss the Next Cheat Code
You just read something most developers never learn. Get more secrets like this delivered every week — JavaScript internals, Python optimizations, AWS architectures, system design, and AI workflows.
Related: How to Build a Modern AWS Data Lake for Operational and Business Analytics with S3, Glue, Athena, Kinesis, and EventBridge · Production IoT Telemetry on AWS: Kinesis, Lambda, DynamoDB, S3, and Event-Driven Device Command Workflows · AWS DynamoDB: Advanced Patterns for Production at Scale
Related: AWS Lambda Best Practices: Write Functions That Scale and Never Time Out · OpenSearch vs pgvector for Codebase RAG on AWS · AWS Lambda Layers: The Dependency Management Pattern You Should Be Using
Watch: 100 Days of AI on YouTube
Short videos from CheatCoders, one AI engineering topic per day.
Most viewed
- Python Decorators Explained: From Simple Wrappers to Production Patterns
- Claude Code vs Cursor vs GitHub Copilot: Choose by Workflow, and Set Up One Repo That Works With All Three
- AI Agent Frameworks in 2025: LangGraph vs CrewAI vs AutoGen vs Raw API
- Python String Methods: Every str Method With Real Production Examples
- REST API Design Best Practices: The Patterns That Make APIs a Joy to Use
Newly added
- AWS Systems Manager Parameter Store: Hierarchical Runtime Config for Coding Agents
- Amazon Cognito Identity Pools: Federate Coding-Agent Tool Callers Without Long-Lived Keys
- Amazon Athena for Coding Agents: Query Tool Audit Logs and Eval Traces on S3 Without a Warehouse
- AWS Batch for Coding Agents: Parallel Overnight PR Reviews and Long-Running Jobs Without Lambda Timeouts
- Amazon Bedrock Prompt Management: Version and A/B Test Coding-Agent System Prompts
Deep-dive PDF
Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.
Already subscribed? or open the subscribe page.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
