Kinesis streams nobody is reading from
What does ZopNight detect here?
ZopNight compares IncomingRecords against GetRecords.Records over 30 days. A stream still receiving data that nothing consumes is the expensive failure mode: you pay per shard-hour to buffer records that then expire unread after the retention period, while producers see successful writes and no error surfaces anywhere.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-180 |
| Category | idle |
| Severity | low |
| Metric | none — pure configuration read |
| Source | kinesis_idle.go |
Where it applies
The dangerous case is not an empty stream
A Kinesis stream with no producers and no consumers is obvious and cheap to reason about. The finding that matters is a stream that is still receiving records nobody reads, with producers writing faithfully into a pipeline whose consumer was decommissioned.
That costs money continuously, per shard-hour, and it fails silently: the producer sees successful writes, no error surfaces anywhere, and the records simply expire after the retention window having been read by nothing.
Two metrics, compared rather than thresholded
IncomingRecords, one of the per-stream series Kinesis publishes to CloudWatch, tells you data is arriving. GetRecords.Records tells you something is
consuming it. The finding is the gap between them, which is why both are required. Either one
alone gives you half the picture.
Where the cost sits
Kinesis bills per shard-hour plus a per-record charge, and the shard count is provisioned rather than automatic on a standard stream. An abandoned consumer does not reduce the shard count, so the stream keeps its full provisioned capacity indefinitely.
Extended retention is worth checking too. A stream configured for 7 or 30 days of retention costs meaningfully more than the 24-hour default, and long retention on a stream nobody reads is paying to keep data for a consumer that no longer exists.
Comparing GetRecords.Records with IncomingRecords
aws cloudwatch get-metric-statistics \ --namespace AWS/Kinesis --metric-name GetRecords.Records \ --dimensions Name=StreamName,Value=my-stream \ --start-time "$(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)" \ --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --period 86400 --statistics SumCompare against IncomingRecords over the same window.
Before deleting
Find the producers first. Deleting a stream that something is still writing to turns silent waste into loud errors in an unrelated service. That is arguably an improvement, but not one to discover by surprise. Stop the producers, confirm the stream drains, then delete.