Querying S3 Logs with Athena and Kinesis Data Firehose
This note describes how to query objects stored in S3 using Athena.
This note describes how to query objects stored in S3 using Athena.

Creating Kinesis Data Firehose
The custom S3 prefixes was introduced in February 2019, allowing you to specify Apache Hive-style prefixes for S3 object keys and use MSCK REPAIR TABLE to create partitions in Athena.
Press Create delivery stream and enter a name.


Choose Direct PUT or other sources.

Skip the record processing settings.

Select Amazon S3 as the destination.

Configure the prefix and error prefix with the following format:
- Prefix:
logs/!{timestamp:'year='yyyy'/month='MM'/day='dd'/hour='HH}/ - Error Prefix:
error_logs/!{timestamp:'year='yyyy'/month='MM'/day='dd'/hour='HH}/!{firehose:error-output-type}

Adjust Buffer size and Buffer interval based on your requirements.

Use GZIP compression to reduce storage costs.

Create or select an IAM role for the delivery stream.

Streaming Data
You can stream data to the Kinesis Data Firehose delivery stream programmatically.
Here’s an example using the AWS SDK for PHP: FirehoseClient#putRecord:
$client = new FirehoseClient([ 'region' => '<AWS_REGION>', 'version' => 'latest',]);
$data = [ 'log_id' => 12345, 'url' => 'https://example.com',];
$client->putRecord([ 'DeliveryStreamName' => '<YOUR_STREAM>', 'Record' => [ 'Data' => json_encode($data) . PHP_EOL, ],]);Creating Athena Table
Select Create table from S3 bucket data in the Athena console.

Enter a database name, table name, and the S3 path used by Firehose.

Specify JSON as the data format.

Define columns based on your data structure.

Configure partitions (e.g., year/month/day/hour) to improve query performance.
Partitioning minimizes the data scanned, significantly reducing costs.

Load partitions with the following command:

MSCK REPAIR TABLE {TABLE_NAME};Querying Athena Table
You can use SQL to query the data efficiently. Example query:
SELECT *FROM table_nameWHERE year = 2019 AND month = 8 AND day = 30LIMIT 10;Best Practices:
- Always include partition keys in the
WHEREclause. - Use the
LIMITstatement to avoid unnecessary scans.
Related posts
Streamlining NDJSON Processing with Kinesis Firehose Dynamic Partitioning
Kinesis Data Firehose recently introduced support for dynamic partitioning. With this, developers no longer require Lambda functions just to convert to NDJSON (Newline Delimited JSON).
Configuring Record Separators for Kinesis Firehose in AWS IoT Core
This note describes how to configure Kinesis Firehose record separator in IoT Core topic rules.
Streaming OPC UA Data to Kinesis via SiteWise Edge Gateway
This note describes how to stream OPC UA data to Kinesis Data Streams through SiteWise Edge Gateway.
Partition Projection in AWS Athena
Athena Partition Projection, introduced in June 2020, eliminates the need to run MSCK REPAIR TABLE to add new partitions manually.
Kinesis Shard Separation Using AWS IoT Topic Payloads
This note describes how to separate Kinesis shards by IoT topic payloads.
