13.6
Amazon Data Firehose
Near-real-time delivery to S3, Redshift and OpenSearch, buffering, transformation, and Firehose vs Data Streams.
18 min Reading + animations
Tip: tap or hover any dotted-underlined term to see what it means.
By the end of this lesson you will be able to
- Explain what Amazon Data Firehose (formerly Kinesis Data Firehose) does: load streaming data into destinations with no consumer code, no servers and no shards.
- Name its sources (Direct PUT, Kinesis Data Streams, Amazon MSK, and AWS services such as CloudWatch Logs, IoT, EventBridge, SNS and WAF) and its destinations (S3, Redshift through S3, OpenSearch, Iceberg tables, Splunk, Snowflake, partners and any HTTP endpoint).
- Predict when Firehose delivers a batch from the buffer size and buffer interval hints, and calculate file sizes, file counts and delays.
- Use Lambda transformation, format conversion to Parquet or ORC, and dynamic partitioning, and know the limits of each.
- Describe what happens when a destination fails: retries, the S3 backup, the 24-hour limit, and duplicates.
- Choose between Kinesis Data Streams and Firehose for an exam scenario, and know when to use both.
#From stream to storage
#The last-mile problem
Lesson 13.5 showed how Kinesis Data Streams collects a fast, endless flow of records. Collecting is only half the job. Sooner or later most of that data must end up somewhere it can be kept and queried: files in S3, tables in Redshift, an index in OpenSearch, a security tool such as Splunk.
Writing that last step yourself is more work than it looks. A consumer that loads a stream into S3 must:
- read every shard and keep track of its position;
- group thousands of small records into files of a sensible size, because millions of tiny files make S3 queries slow and expensive;
- compress, encrypt and name the files so they can be found later;
- retry when the destination is slow or down, without losing or doubling data;
- scale up when traffic grows on match day and back down at night;
- run somewhere, be patched and be monitored.
None of that is your business logic. It is plumbing, and every team would write the same plumbing.
#What Firehose is
Amazon Data Firehose is a fully managed service that takes streaming data and loads it into a destination. You create a Firehose stream, choose a source and a destination, and Firehose does the plumbing: buffering, batching, compression, encryption, optional transformation, delivery and retries. As the notes put it, you do not write any consumer code; it takes the data and stores it directly.
- Serverless and fully managed. There are no servers, no shards and no capacity to plan. Firehose scales up and down on its own.
- Pay for what you use. You pay per GB that goes in (plus optional features), not for idle capacity.
- Near real-time. It collects records in a buffer and delivers them in batches, so data arrives seconds to minutes after it was sent, not milliseconds.
- No storage of its own. It keeps data only until it is delivered (at most 24 hours if delivery keeps failing). There is no replay.
The service was called Amazon Kinesis Data Firehose until February 2024, when AWS renamed it Amazon Data Firehose. Only the name changed: the API, the CLI command (aws firehose), IAM actions (firehose:*) and CloudWatch metrics are the same. Older exam questions and blog posts still say “Kinesis Data Firehose”; it is the same service.
A Firehose stream: from producers to destinations
Records come in from an app, a Kinesis data stream or CloudWatch Logs. Firehose buffers them and delivers batches to S3, Redshift or OpenSearch, with no consumer code of yours.
Scenario
The app writes straight to Firehose; size or time decides when a file lands in S3.
A food-delivery app sends order events with the SDK: up to 500 records or 4 MB in one batch call, each record up to 1,000 KiB. There are no shards to plan; Firehose scales by itself.
#Sources: how data gets in
A Firehose stream has exactly one source, chosen when you create it:
| Source | How it works | Typical use |
|---|---|---|
| Direct PUT | Producers call the Firehose API themselves: PutRecord (one record) or PutRecordBatch (up to 500 records or 4 MiB per call) | Apps with the SDK, the Kinesis Agent on servers, and AWS services that write to Firehose for you |
| Kinesis Data Streams | Firehose reads an existing data stream, like any other consumer | Data that also needs real-time consumers or replay |
| Amazon MSK | Firehose reads a topic of a managed Kafka cluster (since September 2023) | Companies already on Kafka |
Many AWS services deliver through Direct PUT on your behalf, which is why Firehose turns up everywhere in architecture diagrams:
- CloudWatch Logs subscription filters (optionally decompressed by Firehose, since December 2023), and CloudWatch metric streams;
- AWS IoT Core rules (sensor data);
- EventBridge rules, with Firehose as a target;
- SNS subscriptions (lesson 13.4: SNS to S3 through Firehose);
- AWS WAF logs, VPC Flow Logs, Route 53 Resolver query logs, API Gateway access logs, CloudFront standard logs (lesson 11.1).
Some details worth knowing:
- A record is any blob of bytes up to 1,000 KiB (before base64 encoding). The slides say “up to 1 MB”, which is the same idea. Firehose does not care whether it is JSON, CSV, Avro, plain text or binary; only format conversion needs JSON.
- Direct PUT quotas per stream: 500,000 records/s, 2,000 requests/s and 5 MiB/s in N. Virginia, Oregon and Ireland; 100,000 records/s, 1,000 requests/s and 1 MiB/s elsewhere. Firehose raises them by itself when it sees throttling, and you can ask for more. With a Kinesis data stream as the source, this quota does not apply.
- A stream whose source is a Kinesis data stream or MSK does not accept
PutRecordcalls; producers write to the data stream instead. - Side note: in November 2024 AWS previewed databases as a source (change data capture from MySQL and PostgreSQL into Iceberg tables). The preview was removed in September 2025, so it is not a Firehose feature today, and it is not on the exam.
#Destinations: where data goes
Each Firehose stream has one destination (plus an optional S3 bucket for backup, see below):
| Group | Destinations | How Firehose delivers |
|---|---|---|
| Amazon S3 | Any bucket | Joins the buffered records into one object per flush |
| Amazon Redshift | Provisioned cluster or Serverless workgroup | Writes the files to S3 first, then runs a COPY command to load them |
| Amazon OpenSearch | OpenSearch Service domain or OpenSearch Serverless collection (formerly Elasticsearch) | Bulk index requests |
| Apache Iceberg tables | Iceberg tables in S3, including Amazon S3 Tables | Inserts, and updates and deletes too, into the right table (generally available since September 2024) |
| Third-party partners | Splunk, Snowflake (since April 2024), Datadog, New Relic, MongoDB, Dynatrace, Coralogix, Elastic, Sumo Logic, Honeycomb and more | Each partner’s ingestion API |
| Custom HTTP endpoint | Any HTTPS endpoint of your own that follows Firehose’s request format | HTTP POST with the records |
Things to remember:
- Redshift goes through S3. Firehose never inserts rows into Redshift directly. It stages the files in an S3 bucket you choose, then issues
COPY. The cluster (or Serverless workgroup) must be publicly accessible with Firehose’s IP addresses allowed, because Firehose connects to it from outside your VPC. - What is not a destination: DynamoDB, RDS, an SQS queue, an EC2 instance, an EFS file system. To reach those, use an HTTP endpoint you build, or a Lambda consumer on a Kinesis data stream.
- S3 object names. By default the key starts with the UTC date and hour,
YYYY/MM/dd/HH/, and you can add your own prefix in front, or build one with expressions such as!{timestamp:yyyy}. Records are concatenated with no delimiter, so turn on new line delimiter if Athena will read them. - Cross-account and cross-Region delivery are possible (for example a central logging account’s bucket), with the right bucket policy and IAM role.
#Buffering: why it is near real-time
#Size and interval hints
Firehose keeps incoming records in a buffer and delivers the buffer when the first of two conditions is met:
- the buffer size hint (how many MB to collect), or
- the buffer interval hint (how many seconds to wait).
If you set one, you must set the other. They are called hints because Firehose may deliver a little differently when that is more efficient; for example, if delivery falls behind, it raises the buffer size by itself to catch up.
| Destination | Buffer size, MB (default) | Buffer interval, s (default) |
|---|---|---|
| Amazon S3, Iceberg tables, Redshift | 1–128 (5) | 0–900 (300) |
| OpenSearch Service and Serverless | 1–100 (5) | 0–900 (300) |
| Splunk | 1–5 (5) | 0–60 (60) |
| HTTP endpoint and most partners | 1–64 (about 5) | 0–900 (60) |
| Snowflake | 1–128 (1) | 0–900 (0) |
So with the defaults, a record sent to an S3 stream can wait up to five minutes before it lands. That is the meaning of near real-time.
#Zero buffering
The notes (and the classic exam answer) say Firehose buffers for at least 1 minute or 1 MB. That was true until December 2023. Today the interval can be 0 seconds (“zero buffering”): Firehose then does not wait and delivers within a few seconds. Limits:
- not available for the S3 backup copy, nor with dynamic partitioning;
- below 60 seconds Firehose uses multipart uploads to S3, so you pay for more PUT requests, and the files are small;
- check the partner’s recommended hints before lowering them.
Even at 0 seconds Firehose is still the near real-time choice in exam terms. For “real-time, sub-second, custom processing”, the answer stays Kinesis Data Streams with a consumer.
#Working out a flush
The rule is simple: time to fill = buffer size ÷ incoming rate. If that is shorter than the interval, size wins; otherwise the interval wins.
- 50 KB/s into a 5 MB buffer: 5,120 KB ÷ 50 KB/s ≈ 102 s, shorter than 300 s, so a 5 MB file about every 100 seconds; 840 files a day.
- 5 KB/s into the same buffer: 1,024 s to fill, so the 300-second interval wins: a file of 1.5 MB every 5 minutes; 288 files a day.
- 5 KB/s into a 128 MB buffer with a 900 s interval: still the interval, a 4.4 MB file every 15 minutes; 96 files a day, records up to 15 minutes late.
Larger buffers mean fewer, bigger files (cheaper and faster to query) and more delay. Small buffers mean fresher data and the small files problem: S3 charges per PUT, and Athena or Glue spend more time opening tiny files than reading them.
Try the numbers yourself:
Buffer timing lab
A tea garden in Sylhet streams soil and weather readings from its sensors through Firehose into S3. Pick how fast data arrives and the two buffer hints, then run one day and see which hint fires first, how big the files are and how late the data can be.
Incoming data rate
Buffer size hint
Buffer interval hint
Dynamic partitioning
Press “Run one day” to see the result.
Self-checkQuestion
A Firehose stream to S3 uses a 5 MB buffer size and a 300-second interval. Producers send about 20 KB per second. How often does Firehose write a file, and how big is it?
#Transforming data on the way
Firehose can change the data between the source and the destination. The processing order is: de-aggregation (if enabled), Lambda transformation, dynamic partitioning, format conversion, delivery.
#Lambda transformation
Turn on data transformation and give Firehose a Lambda function. Typical jobs: CSV to JSON (or JSON to CSV, as in the notes), masking phone numbers or card numbers, adding fields (a city name from a postcode), dropping debug events, fixing timestamps.
- Firehose keeps a separate buffer for Lambda: 0.2 to 3 MB (default 1 MB, 256 KB for Splunk and Snowflake) or 0 to 900 seconds (default 60).
- It invokes the function synchronously; the request and response are limited to 6 MB, and the function may run at most 5 minutes.
- The function returns each record with the same
recordId, aresultand the newdata(base64).resultisOk(deliver it),Dropped(throw it away on purpose) orProcessingFailed. - If the invocation fails (timeout, throttling), Firehose retries three times by default, then treats the whole batch as failed.
- Failed records go to the
processing-failed/prefix in S3, with the error and the function’s ARN. Nothing disappears silently. - You can keep an untouched copy with source record backup to S3, useful when the transformation has a bug and you need to run it again.
- AWS provides blueprints (sample functions) for common jobs such as Apache log to JSON.
#Format conversion: JSON to Parquet or ORC
For a data lake, columnar formats are far better than JSON: Athena reads only the columns a query needs, and the files compress well. Firehose can convert JSON to Apache Parquet or Apache ORC by itself, without Lambda:
- It needs a schema from a table in the AWS Glue Data Catalog (lesson 17.6).
- It reads the JSON with a deserializer (
OpenX JSON SerDe, the usual choice, orHive JSON SerDe) and writes Parquet or ORC. - The input must be JSON. For CSV or other text, first turn it into JSON with a Lambda transformation.
- Records that do not match the schema go to the error prefix as
format-conversion-failed. - Compression for S3: gzip, Snappy, Zip or Hadoop-compatible Snappy (Redshift: gzip only).
The slides list the formats Firehose “supports” (CSV, JSON, Parquet, Avro, raw text, binary) and the conversions (to Parquet or ORC, compression with gzip or Snappy). Read it as: any bytes can pass through, but the built-in conversion only goes from JSON to Parquet or ORC.
#Dynamic partitioning
By default every file goes under the time prefix. Dynamic partitioning (since 2021) groups records by keys inside the data, such as customer_id or city, and writes each group to its own prefix, for example city=sylhet/2026/10/26/. A query for one city then scans only that folder.
- Keys come from inline parsing with jq (for JSON) or from your Lambda function; up to 50 keys.
- The prefix uses expressions like
!{partitionKeyFromQuery:city}. - S3 destination only. It can be enabled only when you create the stream, and cannot be turned off later.
- Each partition value has its own buffer, so files are smaller and the delay can reach 1.5 times the interval. No zero buffering.
- Quota: 500 active partitions per stream at a time (up to 2,500 on request). Records beyond that go to the error prefix (
activePartitionExceeded). Partition by keys with few values, never by a transaction ID. - It costs extra per GB and per object delivered.
On the way: Lambda, Parquet and dynamic partitioning
A bKash-style payment service streams transaction events into an S3 data lake. Watch Firehose clean them with Lambda, turn them into Parquet with a Glue schema, and file them by customer.
Scenario
Firehose hands batches to your function and keeps only what it returns.
Each event holds the customer’s full phone number. The analysts must never see it, so the data has to be masked before it is stored.
#When delivery fails
Firehose retries, and when it cannot deliver it backs the data up to S3 so you can load it later. Each destination behaves a little differently:
| Destination | What Firehose does on failure |
|---|---|
| S3 | Retries for up to 24 hours (Direct PUT source). After that the data is lost. With a Kinesis data stream or MSK source, it keeps retrying for as long as the source retains the data |
| Redshift | Retries COPY for the retry duration (0–7,200 s, default 3,600), then skips the batch and writes a manifest of the skipped files to errors/ for a manual COPY |
| OpenSearch | Retries for the retry duration (0–7,200 s, default 300), then writes the documents to AmazonOpenSearchService_failed/ in the backup bucket |
| Splunk, HTTP endpoints, partners | Waits for an acknowledgement; on error or timeout retries until the retry duration ends, then backs the data up to S3 |
| Snowflake | Retries service errors (default 60 s); records with schema errors go straight to S3 (snowflake-failed/) |
The S3 backup has two modes for non-S3 destinations: failed data only (the default) or all data (a full copy, handy as a cheap archive). The slides show it as “all or failed data” going to an S3 backup bucket. If both the destination and the backup bucket fail, Firehose pauses delivery until one of them works again.
Delivery is at least once. When an acknowledgement is lost, Firehose sends the batch again, so Splunk, HTTP endpoints, OpenSearch and Redshift can receive duplicates. S3, Iceberg tables and Snowflake are the exceptions. Put an event ID in each record so the destination (or your queries) can remove duplicates.
When a destination fails
A garments exporter sends its security logs to Splunk and its app logs to OpenSearch, with an S3 bucket as the safety net. Break each destination and see what Firehose does.
Scenario
Retry for the retry duration, then park the documents in S3.
The OpenSearch domain is overloaded and rejects the bulk request.
#Security, monitoring and cost
Access. Firehose works with an IAM role that you give it: the role allows it to read the source (for example kinesis:GetRecords), invoke the Lambda function, read the Glue table and write to the bucket. Producers need firehose:PutRecord / PutRecordBatch permission. A broken role is the most common reason delivery stops.
Encryption.
- In transit: all API calls and deliveries use TLS (HTTPS).
- At rest inside Firehose: for Direct PUT, turn on server-side encryption with KMS (an AWS owned key or your own customer managed key). With a Kinesis data stream as the source, Firehose relies on the stream’s encryption instead.
- At the destination: for S3, the bucket’s default encryption or an SSE-KMS key you choose (lesson 10.8).
Networking. Producers in a private subnet can reach Firehose through an interface VPC endpoint without the internet (chapter 22). Firehose can deliver to an OpenSearch domain inside a VPC (it places network interfaces in your subnets, which has its own small charge).
Monitoring. CloudWatch metrics such as IncomingRecords, DeliveryToS3.Success and, the most useful one, DeliveryToS3.DataFreshness: the age of the oldest record not yet delivered. Alarm on freshness, and turn on error logging to CloudWatch Logs.
Cost. You pay per GB ingested (about $0.029 per GB for Direct PUT and Kinesis sources in the first tier), plus extra per GB for format conversion and dynamic partitioning, plus what the destination charges. One trap: for Direct PUT and Kinesis sources, each record is rounded up to the next 5 KB. 1,000 records of 1 KB per second are billed as 5 KB each, five times the real volume; packing them into fewer, larger records (5 KB or more) cuts the ingestion bill.
#Kinesis Data Streams vs Firehose
These two are the classic exam confusion, because both carry streaming data and both were once “Kinesis”.
| Kinesis Data Streams | Amazon Data Firehose | |
|---|---|---|
| Job | Collect a stream and let your consumers process it | Load a stream into a destination |
| Code | You write producers and consumers (Lambda, KCL apps, Flink) | No consumer code; choose a destination (Lambda optional, for transformation) |
| Latency | Real-time: about 200 ms (around 70 ms with enhanced fan-out) | Near real-time: buffer interval 0–900 s (60 s minimum before December 2023) |
| Capacity | Shards in provisioned mode, or on-demand mode that scales for you | Fully managed, automatic scaling, nothing to size |
| Storage | Keeps records 24 hours by default, up to 365 days | No storage; only until delivered (at most 24 h on failure) |
| Replay | Yes, from any position in the retention window | No |
| Consumers | Many, each reading the same data at its own pace | One destination per stream (plus S3 backup) |
| Where data goes | Anywhere your code sends it | S3, Redshift, OpenSearch, Iceberg, Splunk, Snowflake, partners, HTTP |
| Transformation | In your consumer | Built in: Lambda, Parquet/ORC, dynamic partitioning |
| Ordering | Per shard (partition key) | Not a feature you can rely on |
| Pricing | Per shard-hour (provisioned) or per GB (on-demand) | Per GB ingested |
The notes list the speed of Firehose as “minimum 1 minute or 1 MB buffer” and the scaling of Data Streams as “manual shard management”. Both are outdated: Firehose can buffer for 0 seconds since 2023, and Data Streams has had an on-demand mode that scales for you since 2021 (lesson 13.5). The exam still describes Data Streams as the one you size and Firehose as the one that scales itself.
They are not rivals. The most common design uses both: producers write to a Kinesis data stream, a real-time consumer (Lambda or Managed Service for Apache Flink) reads it for alerts and dashboards, and a Firehose stream with that data stream as its source archives everything to S3, often as Parquet, for Athena.
One cricket clickstream: Data Streams, Firehose, or both
During a Bangladesh vs India match, millions of fans tap the live-score app. The product team wants live stats now and a full archive for later. Compare the tools.
Scenario
Real time, replay, many consumers, and your own consumer code.
Every tap is a record with the match ID as partition key. Records are readable about 200 ms after they are written (around 70 ms with enhanced fan-out).
#What goes wrong
| Symptom | Likely cause | Fix |
|---|---|---|
| Data reaches S3 five minutes late | Default 300 s interval with low traffic | Lower the interval (down to 0 s), accept smaller files |
| Millions of tiny objects, slow Athena queries | Small buffer size, short interval, too many partitions | Raise the buffer size (64–128 MB), fewer partition keys, compact later |
Nothing arrives, DataFreshness keeps rising | Firehose’s IAM role lost access to the bucket, or the bucket or KMS key policy changed | Fix the role or the policy; Firehose retries for 24 h (Direct PUT) |
| Data older than a day is missing after an S3 outage of your own making | Direct PUT keeps data at most 24 h | Alarm on freshness; use a Kinesis data stream as the source for longer protection |
PutRecord fails on a new stream | The stream’s source is a Kinesis data stream | Write to the data stream, not to Firehose |
Records appear in processing-failed/ | The Lambda function returned ProcessingFailed, timed out (over 5 min), or returned more than 6 MB | Fix the function; smaller Lambda buffer; replay the failed files |
| Parquet conversion fails for every record | Input is CSV, not JSON, or the Glue schema does not match | Convert CSV to JSON in Lambda first; fix the Glue table |
activePartitionExceeded errors | Partitioning by a key with too many values | Use keys with few values; request more partitions |
| Duplicates in Splunk or OpenSearch | At-least-once delivery after a lost acknowledgement | Event IDs and duplicate removal at the destination |
Redshift loads stopped, files in errors/ | Cluster unreachable or in maintenance longer than the retry duration | Make the cluster reachable; re-run COPY with the manifest |
| Ingestion bill much higher than the data volume | Many records smaller than 5 KB (each is rounded up) | Batch several events into one record |
| Cannot turn dynamic partitioning on (or off) | It is set only at creation and is permanent | Create a new stream |
#Firehose in system design
- Central logging. CloudWatch Logs subscription filters from many accounts → Firehose → S3 in a logging account (archive, Glacier after 90 days) and OpenSearch (search). Lesson 19.2 has the details.
- Security data to a security analytics tool. WAF logs, VPC Flow Logs and CloudTrail (through CloudWatch Logs) → Firehose → Splunk or another partner, with failed data backed up to S3.
- A data lake from clickstreams. App events → Firehose (Lambda clean-up, Parquet, dynamic partitioning) → S3 → Glue Data Catalog → Athena and dashboards. Chapter 17 builds this pipeline end to end.
- Real-time plus archive. Kinesis data stream → Lambda for live alerts, and Firehose from the same stream to S3.
- IoT. Sensors → AWS IoT Core rule → Firehose → S3 for history, with a second rule to a real-time path if needed.
- Fan-out archive. An SNS topic with a Firehose subscription keeps a copy of every published message in S3 (lesson 13.4).
- Streaming into tables. Firehose into Iceberg tables or S3 Tables gives SQL tables that update as data arrives, without a separate ETL job (side note; the exam rarely asks about it yet).
#Try it yourself
Create a Firehose stream to S3 in Singapore, send a few records, and watch them arrive. The role and bucket are examples; the role must trust firehose.amazonaws.com and allow s3:PutObject on the bucket.
# 1. Create a Direct PUT stream to S3: 1 MB or 60 seconds, gzip, custom prefix
aws firehose create-delivery-stream --region ap-southeast-1 \
--delivery-stream-name clicks-example \
--delivery-stream-type DirectPut \
--extended-s3-destination-configuration '{
"RoleARN": "arn:aws:iam::111122223333:role/firehose-clicks-example",
"BucketARN": "arn:aws:s3:::clicks-lake-example",
"Prefix": "clicks/",
"ErrorOutputPrefix": "errors/",
"BufferingHints": { "SizeInMBs": 1, "IntervalInSeconds": 60 },
"CompressionFormat": "GZIP"
}'
# {
# "DeliveryStreamARN": "arn:aws:firehose:ap-southeast-1:111122223333:deliverystream/clicks-example"
# }
# 2. Wait until it is ACTIVE (about a minute)
aws firehose describe-delivery-stream --region ap-southeast-1 \
--delivery-stream-name clicks-example \
--query 'DeliveryStreamDescription.DeliveryStreamStatus'
# "ACTIVE"
# 3. Send one record (CLI v2 needs raw-in-base64-out to send plain text); add \n yourself
aws firehose put-record --region ap-southeast-1 --delivery-stream-name clicks-example \
--cli-binary-format raw-in-base64-out \
--record '{"Data":"{\"match\":\"BAN-IND\",\"event\":\"open_scorecard\"}\n"}'
# {
# "RecordId": "aBcD1234...example",
# "Encrypted": false
# }
# 4. Send a batch (up to 500 records or 4 MiB per call); always check FailedPutCount
aws firehose put-record-batch --region ap-southeast-1 --delivery-stream-name clicks-example \
--cli-binary-format raw-in-base64-out \
--records '[{"Data":"{\"event\":\"share\"}\n"},{"Data":"{\"event\":\"replay\"}\n"}]'
# {
# "FailedPutCount": 0,
# "Encrypted": false,
# "RequestResponses": [ { "RecordId": "..." }, { "RecordId": "..." } ]
# }
# 5. About a minute later (the interval wins: far less than 1 MB was sent), one object appears
aws s3 ls s3://clicks-lake-example/clicks/ --recursive
# 2026-10-26 09:14:03 212 clicks/2026/10/26/09/clicks-example-1-2026-10-26-09-13-02-1a2b3c4d.gz
# 6. Check freshness: the age in seconds of the oldest undelivered record
aws cloudwatch get-metric-statistics --region ap-southeast-1 --namespace AWS/Firehose \
--metric-name DeliveryToS3.DataFreshness \
--dimensions Name=DeliveryStreamName,Value=clicks-example \
--start-time 2026-10-26T09:00:00Z --end-time 2026-10-26T10:00:00Z \
--period 300 --statistics Maximum
# 7. Clean up (Firehose has no fixed fee, but the bucket keeps costing)
aws firehose delete-delivery-stream --region ap-southeast-1 --delivery-stream-name clicks-example
The API still calls a Firehose stream a delivery stream, a leftover from the old name. Try changing the hints with aws firehose update-destination (it needs the current version ID from describe-delivery-stream) and watch the file sizes change.
#Summary
Key takeaways
- Amazon Data Firehose (called Kinesis Data Firehose until February 2024) loads streaming data into destinations: fully managed, serverless, automatic scaling, pay per GB, no consumer code, no storage and no replay.
- Sources (one per stream): Direct PUT (SDK
PutRecord/PutRecordBatch, Kinesis Agent, CloudWatch Logs, IoT, EventBridge, SNS, WAF, VPC Flow Logs…), Kinesis Data Streams, Amazon MSK. Records up to 1,000 KiB. - Destinations (one per stream): S3, Redshift (S3 first, then
COPY), OpenSearch, Iceberg tables / S3 Tables, Splunk, Snowflake, partners (Datadog, New Relic, MongoDB…), custom HTTP endpoint. - Buffering: deliver when the size (S3: 1–128 MB, default 5) or the interval (0–900 s, default 300) is reached first. Near real-time. Zero buffering exists since December 2023; the old “minimum 60 s” is outdated.
- Lambda transformation (CSV to JSON, masking;
Ok/Dropped/ProcessingFailed, 5-minute and 6 MB limits), format conversion JSON to Parquet/ORC with a Glue Data Catalog schema (no Lambda needed), dynamic partitioning by keys in the data (S3 only, set at creation, 500 active partitions). - Failures: retries, then S3 backup (failed data or all data); S3 retries up to 24 h for Direct PUT, then data is lost; Redshift manifests in
errors/. At-least-once: duplicates possible except for S3, Iceberg and Snowflake. - Data Streams vs Firehose: real-time, replay, many consumers, your code, shards or on-demand → Data Streams. Load into storage, no code, near real-time, auto scaling → Firehose. Often both: Data Streams → Firehose → S3.
Answer on your own first, then read the explanation, even when you got it right.
Self-checkQuestion
What is the main job of Amazon Data Firehose?
Self-checkQuestion
An older practice question mentions Amazon Kinesis Data Firehose. How does it relate to Amazon Data Firehose?
Self-checkQuestion
With default settings, when does a Firehose stream with an S3 destination deliver its buffer?
Self-checkQuestion
Which of these is NOT a destination that Firehose can deliver to?
Self-checkQuestion
How does Firehose deliver data to Amazon Redshift?
Self-checkQuestion
What is the largest single record a producer can send to Firehose?
Self-checkQuestion
Which two can be the source of a Firehose stream?
Choose 2
Self-checkQuestion
A media company wants to store all clickstream events from its website in S3 for later analysis. It wants the least operational overhead and no custom code. Data may arrive a few minutes late. What should it use?
Self-checkQuestion
A betting company needs a dashboard that updates in under a second as bets are placed, with custom logic to spot unusual patterns. Which service should ingest the bets?
Self-checkQuestion
Three teams need to read the same stream of IoT sensor data independently, and the data science team wants to reprocess the last three days after fixing a bug. What fits?
Self-checkQuestion
A Firehose stream to S3 has a 5 MB buffer size and a 300-second interval. It receives a steady 20 KB per second. What happens?
Self-checkQuestion
Tea garden sensors send 2 KB per second in total to a Firehose stream with a 128 MB buffer and a 900-second interval. Roughly how big is each S3 file, and how many files arrive per day?
Self-checkQuestion
An app sends 1,000 records per second to Firehose with Direct PUT, each record 1 KB. Ingestion costs $0.029 per GB, and records are billed in 5 KB increments. About how much is the ingestion bill for a 30-day month, and what reduces it most?
Self-checkQuestion
Which two statements about Firehose data transformation with Lambda are correct?
Choose 2
Self-checkQuestion
A team wants Firehose to write Parquet files to S3 so Athena queries scan less data. The events are JSON. What must they provide?
Self-checkQuestion
A legacy system sends events as CSV lines. The analytics team wants Parquet in S3 through Firehose. What design works?
Self-checkQuestion
A team has run a Firehose stream to S3 for a year and now wants to partition the files by customer_id using dynamic partitioning. What must they do?
Self-checkQuestion
After enabling dynamic partitioning by transaction_id, most records end up in the S3 error prefix as active-partition-exceeded errors. Why, and what is the fix?
Self-checkQuestion
A Firehose stream uses Direct PUT and delivers to S3. A bad change removes the role’s permission on the bucket, and nobody notices for two days. What happens to the data sent during that time?
Self-checkQuestion
An OpenSearch domain behind a Firehose stream is down for two hours. The retry duration is the default. What happens to the log documents?
Self-checkQuestion
Which two destinations can receive duplicate records from Firehose after a retry?
Choose 2
Self-checkQuestion
The owner’s notes say Firehose always buffers for at least one minute or 1 MB. What is correct today?
Self-checkQuestion
A team creates a Firehose stream with an existing Kinesis data stream as its source. Developers then try to call PutRecord on the Firehose stream and get errors. Why?
Self-checkQuestion
Which CloudWatch metric best shows that a Firehose stream to S3 is falling behind or stuck?
Self-checkQuestion
Which two statements comparing Kinesis Data Streams and Firehose are correct?
Choose 2
Self-checkQuestion
Producers write directly to a Firehose stream with Direct PUT. Compliance requires the data to be encrypted at rest while Firehose holds it, with a key the company controls. What should they do?
Self-checkQuestion
A security team sends WAF logs through Firehose to Splunk and also wants a complete copy of every log in S3 for seven years. What is the simplest design?
Self-checkQuestion
Which statement about Amazon Data Firehose is NOT true?
Self-checkQuestion
Which two requirements point to Amazon Data Firehose rather than Kinesis Data Streams alone?
Choose 2
Self-checkQuestion
A tea estate’s sensors publish readings through AWS IoT Core. The agronomist needs weekly trends in Athena; data can be 15 minutes old. What is the most operationally simple pipeline?
Self-checkQuestion
A Lambda transformation that calls an external address-cleaning API sometimes needs 8 minutes per batch. Records keep appearing in processing-failed/. What is the cause?