Based on the MLS-C01 exam guideReport an error
Training data has to flow in from somewhere. Click logs, IoT sensors, and transaction events pour in as real-time streams, while data from operational databases and external systems arrives in periodic batches. "Kinesis" is easy to confuse by name alone, so you need to tell the services apart precisely.
| Service | Role | Key characteristics | Typical ML use |
|---|---|---|---|
| Data Streams (KDS) | Real-time stream ingestion and storage | Shard-based, requires consumer code, data retention (up to 365 days), replay possible | Multi-consumer event bus, reprocessing |
| Data Firehose | Stream-to-destination delivery | Fully managed, auto-delivers to S3/Redshift/OpenSearch, buffering and format conversion | Accumulating a data lake |
| Managed Service for Flink | Real-time stream analytics | Windowed aggregation and anomaly detection with SQL/Flink | Real-time feature computation |
| Video Streams | Video stream ingestion | Input for video ML | Face recognition, video analysis |
How will you use the stream data?
├─ Only need automatic delivery to a destination (S3/Redshift/OpenSearch) → Firehose
│ · no consumer code · buffering (by size or time) · Parquet conversion and compression available
└─ Several consumers process the same stream differently,
or you need custom processing / replay after a failure → Data Streams
· shard management · retention · independent offset per consumer
import boto3, json
kinesis = boto3.client("kinesis")
# Put an event into Data Streams — PartitionKey distributes across shards
kinesis.put_record(
StreamName="clickstream",
Data=json.dumps({"user_id": "u123", "event": "click", "ts": 1719300000}),
PartitionKey="u123", # same key → same shard → unit of ordering guarantee
)# Firehose: automatic delivery to S3 with no code + buffering settings (example delivery stream configuration)
firehose = boto3.client("firehose")
firehose.put_record(
DeliveryStreamName="to-datalake",
Record={"Data": json.dumps({"user_id": "u123", "amount": 42.0}) + "\n"},
)
# Once the buffer fills (e.g., 5MB or 60 seconds), Firehose converts to Parquet, compresses, and loads into S3KDS scales throughput in units of shards. One shard handles 1MB/s and 1,000 records/s of writes and 2MB/s of reads, so as traffic grows you must add shards (or use on-demand mode). KDS also retains data, so multiple consumers can read the same data independently and reprocess it (replay). Firehose, by contrast, has no retention or replay and is a "fire and forget" pipe responsible only for loading into a destination.
⚠️ Pitfall: "It's real time, so it must be KDS" is a trap answer. If the passage has only one consumer and hints such as "without code" or "minimal management overhead," Firehose is the answer. Conversely, if you see "reprocessing" or "multiple teams each consuming," Firehose is eliminated.
AWS Glue is a serverless service that bundles three things.
# Glue ETL job (PySpark) — read a catalog table, clean it, and save as Parquet
import sys
from awsglue.context import GlueContext
from awsglue.transforms import DropNullFields
from pyspark.context import SparkContext
glueContext = GlueContext(SparkContext.getOrCreate())
# Load the table the crawler registered in the catalog as a DynamicFrame
dyf = glueContext.create_dynamic_frame.from_catalog(
database="raw_db", table_name="clickstream"
)
clean = DropNullFields.apply(frame=dyf) # drop null columns
# Save as Parquet in the training feature location (with partitioning)
glueContext.write_dynamic_frame.from_options(
frame=clean,
connection_type="s3",
connection_options={"path": "s3://my-lake/features/", "partitionKeys": ["dt"]},
format="parquet",
)Glue's DynamicFrame is an ML/ETL-friendly extension of the Spark DataFrame that can handle semi-structured data with inconsistent schemas (such as JSON) without enforcing a schema (rows with schema mismatches are preserved rather than discarded). Once structured transformation is done, call toDF() to convert to a regular Spark DataFrame and use familiar operations. Thanks to the Data Catalog populated by the Crawler, you can explore data immediately with SQL in Athena, which speeds up the data-understanding (EDA) stage before ML preprocessing.
| Tool | What it does | What it does not do |
|---|---|---|
| Glue Crawler | Infers schema + registers catalog tables | Does not move or transform data |
| Glue ETL Job | Cleans, joins, aggregates, and converts formats with Spark | Does not handle real-time stream ingestion |
| Kinesis Firehose | Loads a stream into a destination | Does not support retention, replay, or multiple consumers |
| Athena | SQL queries over the catalog | Is not an engine for large-scale repeated ETL |
| DMS | DB → data lake migration and CDC | Does not do feature engineering |
Not all data arrives as a stream. You also need to know the paths from operational databases, external files, and on-premises storage.
| Tool | What it does | When to choose it |
|---|---|---|
| AWS DMS | DB → S3/Redshift migration and CDC (change data capture) | When continuously flowing changes from an operational RDB into a data lake |
| AWS DataSync | Bulk transfer between on-premises NFS/SMB and S3/EFS/FSx | When periodically moving training data from an internal file server |
| AWS Snow family | Large offline transfer using physical devices | When the data is too large or the network link too slow to move over the network |
| AWS Batch / EMR | Runs large-scale batch computation | When running heavy transformations and aggregations after ingestion |
| Direct S3 upload | The simplest way to load | When the files are already in hand and the scale is small |
⚠️ Pitfall: If a passage says "we need to move petabytes" and you choose network transfer (DataSync) without thinking, you miss the constraint of line speed. If there is a hint that the transfer would take weeks, the Snow family is the candidate answer.
Streaming is operationally harder than batch. The exam reflects this difficulty directly.
PartitionKey to the user ID.ML data ingestion splits into two patterns.
| Aspect | Batch | Streaming |
|---|---|---|
| Arrival pattern | Periodic bulk loads (daily/hourly) | As soon as each event arrives |
| Typical tools | Glue, EMR, Batch, S3 | Kinesis, MSK (Kafka) |
| Latency | Minutes to hours | Seconds to milliseconds |
| Training fit | Most model retraining | Real-time features, online learning |
| Freshness | Staleness acceptable | Recency is the value |
| Operational difficulty | Low (rerun on failure) | High (ordering, duplicates, late data handling) |
[Lambda architecture]
Events ──┬─▶ KDS ─▶ Flink (windowed aggregation) ─▶ real-time features ─▶ inference endpoint
│ (speed layer: low latency, approximate)
└─▶ Firehose ─▶ S3 data lake ─▶ batch retraining ─▶ model update
(batch layer: accurate, complete)
The lambda architecture processes the same data simultaneously through a speed layer (streaming, low-latency approximation) and a batch layer (periodic, accurate and complete), combining the strengths of both. In ML it is commonly used as follows: accumulate every event in S3 via Firehose (for batch retraining) while computing real-time features with KDS + Flink (for immediate inference). However, if the feature computation logic of the two paths diverges, training-serving skew arises, so consistency management is important.
The real cost of the lambda architecture is not infrastructure but maintaining the logic twice. If "transaction count in the last 5 minutes" is computed differently in the real-time path and the batch path, the model receives values at inference time that it never saw during training. The standard remedy is to consolidate the definition in one place with a Feature Store.
Firehose does not just "deliver." You can insert light processing along the way, so the range of correct answers for simple-loading scenarios is wider than you might think.
Do not jump to "we need a light transformation, so Firehose is out." For simple per-record transformations, Firehose + Lambda is enough; Glue ETL or Flink appears only when you need operations that cut across multiple records, such as joins and aggregations.
When solving exam scenarios, ask the following in order.
These five questions solve most ingestion problems.
Tomorrow we cover attaching ground truth to the data collected this way (SageMaker Ground Truth, active learning, label quality).
Click a choice to reveal the answer and explanation.
Question 1
An IoT sensor stream just needs to be automatically delivered as-is into an S3 data lake as Parquet, with no separate transformation or code. Which service fits best?
Question 2
A single clickstream must be consumed independently by (1) a real-time dashboard, (2) a fraud detection model, and (3) later reprocessing, and the data must be re-readable after a failure. Which service fits?
Question 3
A large volume of JSON logs with unknown schemas has piled up in S3. Before starting SQL exploration with Athena, you want to automatically create the tables and schemas. Which tool do you use?
Question 4
What is the biggest reason most ML model retraining happens in batch rather than streaming?
Question 5
Which architecture pattern uses the same event data for both real-time feature computation (immediate inference) and periodic model retraining (accurate and complete)?