Generated banner for Managing Amazon Kinesis Data Streams
Generated logo for Managing Amazon Kinesis Data Streams

Managing Amazon Kinesis Data Streams

AWSOfficialPublished by AWS

  • Skill
  • Tool integration
  • Cloud and DevOps
  • Apache-2.0
  • No issues found

From the author

Operates Amazon Kinesis Data Streams (KDS). Covers streaming tables and Amazon S3 delivery - serverless, fully managed delivery from a KDS stream to Apache Iceberg tables on S3 Tables or to general-purpose S3 buckets. Includes channel setup, IAM, schemas, output key templates, CloudWatch metrics and alarms, DLQ handling, quotas, and troubleshooting. For all other KDS topics and questions, search AWS documentation and blogs instead. Triggers: Kinesis Data Streams, KDS, streaming tables, stream to S3, stream to Iceberg, stream to S3 Tables, KDS delivery, KDS channel, CreateChannel, data channel, data freshness, dead-letter queue, KDS lakehouse, serverless Kinesis delivery, Firehose alternative for KDS, zero-ops Kinesis to S3. DO NOT USE for Kinesis Data Firehose, Kinesis Video Streams, or Managed Service for Apache Flink — use dedicated skills or search documentation instead.
— the description by AWS

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides operational guidance for configuring and managing Amazon Kinesis Data Streams (KDS) delivery channels. It focuses on serverless, zero-ops delivery of stream data directly to Apache Iceberg tables on S3 Tables or general-purpose S3 buckets. The skill covers channel lifecycle management, IAM configuration, monitoring via CloudWatch, and troubleshooting common delivery issues, ensuring efficient data movement without the need for additional consumers or Flink applications.

What it does

  • Configures KDS channels for direct delivery to S3 or Apache Iceberg tables.
  • Provides IAM policy templates for secure service execution.
  • Explains monitoring strategies using CloudWatch metrics and delivery logs.
  • Outlines troubleshooting steps for failed channels and data freshness issues.
  • Defines hard limits and prerequisites for KDS delivery configurations.

When to use it

  • When you need to deliver KDS data to S3 or Iceberg tables without managing consumers.
  • When building a data lake or lakehouse architecture on AWS.
  • When you require a serverless, append-only delivery mechanism for streaming data.
  • When troubleshooting delivery failures or monitoring data freshness in KDS channels.

Advantages

  • Eliminates the need for managing Kinesis consumers or Flink applications.
  • Channels consume no shard capacity or enhanced fan-out slots.
  • Fully managed, serverless delivery architecture.
  • Supports direct integration with Apache Iceberg for queryable streaming data.

Usage examples

“How do I set up a channel to deliver Kinesis stream data to an S3 bucket?”
The agent provides the necessary IAM trust and permission policies, along with the configuration steps for the general-purpose S3 delivery channel.
“My Kinesis delivery channel is ACTIVE but no data is appearing in S3. How do I debug this?”
The agent guides you to check CloudWatch metrics like FailedRecordCount, verify IAM permissions, and enable delivery logging to identify potential access or schema errors.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/aws/managing-amazon-kinesis-data-streams/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip managing-amazon-kinesis-data-streams.zip -d .agents/skills

Documentation by AWS

Amazon Kinesis Data Streams

Overview

Domain expertise for Amazon Kinesis Data Streams. This skill covers streaming tables and Amazon S3 delivery, which provide serverless, fully managed delivery from a KDS stream directly to Apache Iceberg tables on S3 Tables or to general-purpose S3 buckets — no consumers, no Firehose, no Flink required for append-only delivery.

Delivery is configured as a channel on a stream via CreateChannel. Channels consume no shard capacity and no enhanced fan-out slots, so they do not compete with existing consumers.

The AWS MCP server is recommended for executing AWS operations. When the MCP server is not available, use the AWS CLI or shell commands instead.

Which Workflow Do You Need?

Customer IntentReference
Deliver stream data to Apache Iceberg tables on S3 Tables — setup, IAM, Glue schema, type mapping, partitioning, channel lifecyclereferences/streaming-tables.md
Deliver stream data to a general-purpose S3 bucket as objects — setup, IAM, compression, storage class, output key templates, channel lifecyclereferences/general-purpose-delivery-to-s3.md
Build a lakehouse / data lake from Kinesis; make streaming data queryable in Athenareferences/streaming-tables.md
Zero-ops, serverless alternative to Firehose or Kinesis consumers for KDS → S3 deliveryreferences/general-purpose-delivery-to-s3.md
CloudWatch metrics and alarms, delivery logging, CloudTrail, encryption, channel states, quotas, naming rules, what can be updatedreferences/monitoring-security-and-limits.md
Channel is ACTIVE but no data arrives; records landing in the DLQ; rising data freshnessStart with references/monitoring-security-and-limits.md, then the destination-specific troubleshooting table
Deliver to both S3 and S3 Tables from one streamSupported — create one channel per destination

Prerequisites

Both destinations require an ON_DEMAND stream — provisioned-mode streams are not supported. Each channel also needs an IAM service execution role trusted by kinesis.amazonaws.com, and a destination in the same Region as the stream.

Hard Limits to Check First

These rule out the feature entirely, so confirm them before designing a solution:

  • Append-only — no CDC, upserts, or deletes

  • No schema evolution — a schema change means deleting and recreating the channel

  • No backfill — only records produced after the channel is ACTIVE are delivered

  • No transformations — records are delivered as-is

  • New table per channel — cannot deliver into an existing Iceberg table

  • Data freshness is 300–900 seconds — not sub-minute

  • Same Region only — cross-account is supported, cross-Region is not

If any of these block the customer, recommend Managed Service for Apache Flink instead.

Additional Resources

Files

references/general-purpose-delivery-to-s3.md

General purpose delivery to Amazon S3

Delivers records from a Kinesis stream to a general-purpose S3 bucket as objects, with configurable compression, storage class, and output key layout. Serverless, no consumer management, 5-minute minimum data freshness. Records are delivered in their original source format — no transformation is applied.

Records are batched into objects: multiple stream records land in a single S3 object, keyed by the output key template.

See monitoring-security-and-limits.md for metrics, alarms, channel states, encryption, quotas, and update constraints.

Constraints

  • ON_DEMAND streams only — provisioned-mode streams are not supported

  • Data freshness is 300–900 seconds. No minimum throughput requirement for the 5-minute window

  • No backfill — only records produced after the channel is ACTIVE are delivered

  • No transformations, filtering, or CDC

  • Cross-Region delivery is not supported; the bucket must be in the stream's Region

  • One S3 channel and one S3 Tables channel per stream at launch — adjustable, and expected to rise over time. Channel reads consume no additional shard capacity

If the customer needs transformations, filtering, or CDC, recommend Managed Service for Apache Flink instead.

Prerequisites

  • KDS stream in ON_DEMAND mode

  • General-purpose S3 delivery bucket in the same Region as the stream

  • General-purpose S3 bucket for the DLQ — optional here; if omitted, errors are written to the delivery bucket under an error prefix. Configure one explicitly so failures do not land among delivered records

  • IAM service execution role (see IAM Setup below)

  • Customer-managed KMS key if using SSE-KMS (recommended)

Record Formats

RecordFormatDescription
BYTE_ARRAYRaw bytes written as-is — no schema
STRINGUTF-8 string records written as-is
JSONPlain JSON records
GSR_JSONGSR-serialized JSON — schema ID embedded per record; requires GSRSchemaARN

Only GSR_JSON requires a schema registry. When the customer asks for "raw" delivery, byte-for-byte copies, or does not mention a specific serialization, use BYTE_ARRAY — it writes each record's bytes unmodified regardless of source encoding. Use JSON or STRING only when the customer explicitly describes their records as JSON or plain text.

Destination Options

OptionValuesNotes
CompressionNONE, GZIP, ZSTDRequired. GZIP balances ratio and speed; ZSTD gives a higher ratio with faster decompression
StorageClassSTANDARD, INTELLIGENT_TIERING, GLACIER_IRDefaults to STANDARD
OutputKeyTemplateTemplate stringOptional — a default is applied if omitted
DataFreshnessInSeconds300–900Defaults to 300

IAM Setup

Trust Policy
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "kinesis.amazonaws.com"},
    "Action": "sts:AssumeRole",
    "Condition": {
      "StringEquals": {"aws:SourceAccount": "ACCOUNT_ID"},
      "ArnLike": {"aws:SourceArn": "arn:aws:kinesis:REGION:ACCOUNT_ID:channel/*"}
    }
  }]
}
Permission Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DeliveryBucketList",
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::DELIVERY_BUCKET",
        "arn:aws:s3:::DELIVERY_BUCKET/*"
      ]
    },
    {
      "Sid": "DeliveryBucketWrite",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:UploadPart",
        "s3:CompleteMultipartUpload",
        "s3:CreateMultipartUpload",
        "s3:ListMultipartUploads",
        "s3:ListMultipartUploadParts"
      ],
      "Resource": "arn:aws:s3:::DELIVERY_BUCKET/PREFIX*"
    },
    {
      "Sid": "DLQBucketAccess",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetBucketLocation",
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads",
        "s3:UploadPart",
        "s3:CompleteMultipartUpload",
        "s3:CreateMultipartUpload",
        "s3:ListMultipartUploadParts"
      ],
      "Resource": [
        "arn:aws:s3:::DLQ_BUCKET",
        "arn:aws:s3:::DLQ_BUCKET/*"
      ]
    },
    {
      "Sid": "KMSAccess",
      "Effect": "Allow",
      "Action": ["kms:Decrypt", "kms:GenerateDataKey", "kms:DescribeKey"],
      "Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/KEY_ID"
    },
    {
      "Sid": "KMSAccessDLQ",
      "Effect": "Allow",
      "Action": ["kms:Decrypt", "kms:GenerateDataKey"],
      "Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/DLQ_KEY_ID",
      "Condition": {
        "StringEquals": {"kms:ViaService": "s3.REGION.amazonaws.com"},
        "StringLike": {"kms:EncryptionContext:aws:s3:arn": "arn:aws:s3:::DLQ_BUCKET/*"}
      }
    },
    {
      "Sid": "CloudWatchLogsAccess",
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogStreams"
      ],
      "Resource": "arn:aws:logs:REGION:ACCOUNT_ID:log-group:/aws/kinesis/CHANNEL_NAME:*"
    }
  ]
}

Statement notes:

  • KMSAccess covers the delivery bucket. Grant it unconditionally — do not add a kms:ViaService/EncryptionContext condition. CreateChannel validates the role's KMS access with a direct KMS call, not one proxied through S3, so a ViaService: s3.REGION.amazonaws.com condition passes at runtime delivery but fails channel creation. Include kms:DescribeKey alongside kms:Decrypt/kms:GenerateDataKey.

  • KMSAccessDLQ is required when the DLQ bucket uses SSE-KMS. Omit if the DLQ uses SSE-S3 (AES-256).

  • The aws/kinesis managed key cannot be used for destination encryption — use a customer managed KMS key with its full ARN.

  • CloudWatchLogsAccess is required whenever delivery logging is enabled. Without it, delivery errors are invisible.

Cross-account delivery

Supported within the same Region. Attach a bucket policy on the destination bucket granting the source account's execution role s3:PutObject (plus the multipart actions above) on the delivery prefix.

Create the Channel

1. Create supporting resources
aws s3 mb s3://my-kds-delivery-$ACCOUNT --region $REGION
aws s3 mb s3://my-kds-dlq-$ACCOUNT --region $REGION

# CW log group — create before the channel
aws logs create-log-group \
  --log-group-name "/aws/kinesis/my-s3-channel" --region $REGION
aws logs put-retention-policy \
  --log-group-name "/aws/kinesis/my-s3-channel" \
  --retention-in-days 30 --region $REGION

Configure SSE-KMS on both buckets.

2. Create the channel

Pass --service-execution-role-arn, --stream-configuration-list, --s3-destination-configuration, and --logging-configuration as separate top-level parameters. If StorageConfiguration.OutputKeyTemplate is set, write that JSON blob to a file and reference it with file:// — the !{...} template syntax gets mangled by shell quoting (even single quotes) when passed inline. Other JSON blobs without !{...} can be passed inline or via file interchangeably.

cat > s3-dest.json << 'EOF'
{
  "DataFreshnessInSeconds": 300,
  "DeadLetterQueueS3Configuration": {
    "BucketARN": "arn:aws:s3:::my-kds-dlq-ACCOUNT_ID",
    "ExpectedBucketOwner": "ACCOUNT_ID",
    "ErrorOutputPrefix": "errors/my-s3-channel/"
  },
  "StorageConfiguration": {
    "BucketARN": "arn:aws:s3:::my-kds-delivery-ACCOUNT_ID",
    "ExpectedBucketOwner": "ACCOUNT_ID",
    "StorageClass": "STANDARD",
    "CompressionType": "GZIP",
    "OutputKeyTemplate": "data/!{channel-name}/!{yyyy}/!{MM}/!{dd}/!{HH}/!{channel-id}-!{mm}!{extension}"
  }
}
EOF

aws kinesis create-channel \
  --region $REGION \
  --channel-name my-s3-channel \
  --service-execution-role-arn $SER_ARN \
  --stream-configuration-list '[{"StreamARN": "'$STREAM_ARN'", "RecordConfiguration": {"RecordFormatType": "BYTE_ARRAY"}}]' \
  --s3-destination-configuration file://s3-dest.json \
  --logging-configuration '{"CloudWatchLogs": {"Enabled": true, "LogGroupName": "/aws/kinesis/my-s3-channel", "LogStreamName": "DestinationDelivery"}}'

ExpectedBucketOwner (12-digit account ID) is required on both DeadLetterQueueS3Configuration and StorageConfiguration. CompressionType (NONE/GZIP/ZSTD) is required inside StorageConfiguration. OutputKeyTemplate is optional there — see the Output Key Template section below for the supported variables.

For STRING, JSON, or GSR_JSON, set RecordFormatType accordingly in stream-config.json. For GSR_JSON, also add "GSRSchemaARN": "arn:aws:glue:...".

3. Wait for ACTIVE
aws kinesis describe-channel \
  --region $REGION \
  --channel-arn $CHANNEL_ARN \
  --query 'ChannelDescription.ChannelStatus'
4. Produce test records
aws kinesis put-record \
  --region $REGION \
  --stream-arn $STREAM_ARN \
  --data "test-record" --partition-key "key1" \
  --cli-binary-format raw-in-base64-out

Output Key Template

Default when OutputKeyTemplate is omitted:

kinesis-channel/!{channel-name}/!{channel-id}/!{yyyy}/!{MM}/!{dd}/!{HH}/!{channel-name}-!{channel-id}-!{yyyy}-!{MM}-!{dd}-!{HH}-!{mm}!{extension}
Variables
VariableDescriptionExample
!{channel-name}Channel namemy-channel
!{channel-id}Channel identifierabc123def456
!{stream-name}Source Kinesis Data Streams stream namemy-stream
!{yyyy}Four-digit year (UTC)2026
!{yy}Two-digit year (UTC)26
!{MM}Month, zero-padded (UTC)07
!{dd}Day of month, zero-padded (UTC)20
!{HH}Hour, 24-hour zero-padded (UTC)14
!{mm}Minute, zero-padded (UTC)30
!{extension}File extension implied by Compression.gz, .zst

Use !{channel-id} combined with time variables down to !{mm} to keep object keys unique across delivery cycles — the default template above is a working pattern for this.

Rules
  • Maximum 1024 characters

  • Must contain at least one variable

  • Must not start or end with /

  • Must not contain path traversal (..)

  • All variable references must be balanced (matching !{ and })

  • Allowed characters: alphanumerics, hyphens, underscores, periods, forward slashes, and variable references

Examples
TemplateValidReason
data/!{channel-name}/!{yyyy}/!{MM}/!{dd}/!{HH}/!{channel-id}-!{mm}!{extension}YesHas variables, unique per channel/minute
!{channel-name}/!{yyyy}-!{MM}-!{dd}/!{HH}!{mm}-!{channel-id}!{extension}YesValid characters, date-based prefix
!{channel-name}/!{channel-id}/!{yyyy}!{MM}!{dd}!{HH}!{mm}YesMinimal valid template
/data/!{channel-name}/!{yyyy}NoStarts with /
data/!{channel-name}/!{yyyy}/NoEnds with /
data/../!{channel-name}/!{yyyy}NoPath traversal
static-prefix-onlyNoNo variables
data/!{channel-name}/!{yyyyNoUnbalanced reference

Match the template to downstream query patterns — use date-based prefixes when consumers filter by time range.

Channel Management

All lifecycle calls except create-channel and list-channels identify the channel by --channel-arn alone — not stream ARN + channel name.

# Describe
aws kinesis describe-channel --region $REGION --channel-arn $CHANNEL_ARN

# List channels on a stream
aws kinesis list-channels --region $REGION --stream-filter "{\"StreamARN\": \"$STREAM_ARN\"}"

# Update — only DataFreshnessInSeconds and logging are mutable
aws kinesis update-channel --region $REGION \
  --channel-arn $CHANNEL_ARN \
  --s3-destination-configuration '{"DataFreshnessInSeconds": 600}'

# Delete — already-delivered objects are NOT removed
aws kinesis delete-channel --region $REGION \
  --channel-arn $CHANNEL_ARN

Destination bucket, output key template, record format, service role, and source stream are immutable. Delete all channels on a stream before deleting the stream.

Verify Delivery

# Delivered objects — wait DataFreshnessInSeconds after producing
aws s3 ls s3://my-kds-delivery-$ACCOUNT/data/ --recursive

# Failed records
aws s3 ls s3://my-kds-dlq-$ACCOUNT/errors/ --recursive

# Delivery errors
aws logs filter-log-events \
  --log-group-name "/aws/kinesis/my-s3-channel" --region $REGION

Troubleshooting

SymptomLikely CauseAction
Channel stuck in CREATING, then FAILEDInvalid role ARN, insufficient permissions, or bucket missing / in another RegionRead ChannelStatusReason from describe-channel. FAILED is not recoverable — fix, delete, recreate
No objects in the delivery prefixRecords produced before ACTIVE (no backfill), or silent delivery failureConfirm records were sent after ACTIVE; check logs and DLQ
Objects in DLQRecord format does not match the configured RecordFormat, KMS failure, or template rendering errorInspect DLQ keys and bodies plus CloudWatch Logs
No CloudWatch logs writtenService role missing logs:CreateLogStream / logs:PutLogEventsAdd CloudWatch Logs permissions
AccessDenied in logsRole policy or bucket policy changed after creation, trust policy broken, or KMS key policy denies accessReview the role policy, bucket policy, trust policy, and KMS key policy
Rising DataChannel.DataFreshnessLow throughput against a low freshness settingRaise DataFreshnessInSeconds so more data batches per cycle
Channel suspendedBucket owner mismatch or destination unavailableCannot be resumed — create a new channel
Channel not available for the streamStream is in provisioned modeSwitch the stream to On-Demand

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an MCP server

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
AWS
Publisher
AWS (Official)
Source
aws/agent-toolkit-for-aws · skills/specialized-skills/analytics-skills/managing-amazon-kinesis-data-streams · commit 0a218f8
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • NOTICE (added by AutoGineer from NOTICE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by AWS.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download managing-amazon-kinesis-data-streams.zip