DynamoDB Streams
DynamoDB Streams ist ein Change-Data-Capture-Log: Jeder Insert, jedes Update und jedes Delete an einer Tabelle wird der Reihe nach als Stream von Records erfasst, auf die du reagieren kannst. So machst du aus einer Tabelle eine Event-Quelle, ohne sie zu pollen.
Im Audit-Log-Szenario willst du in dem Moment reagieren, in dem ein sensibles Event landet — einen Alert auslösen, wenn jemand eine Rechnung exportiert oder eine Admin-Rolle vergibt — ohne die Tabelle auf einem Timer zu scannen. Streams ist die Push-Seite davon.
Wie funktionieren DynamoDB Streams?
DynamoDB Streams erfassen jeden Insert, jedes Update und jedes Delete an einer Tabelle als zeitlich geordnetes, dedupliziertes Log von Records, das bis zu 24 Stunden aufbewahrt wird. Du wählst, was jeder Record trägt, über StreamViewType (nur Keys, das neue Image, das alte Image oder beide), und konsumierst den Stream dann mit einem Lambda-Trigger, um auf Item-Änderungen zu reagieren – ohne Polling.
- Streams erfasst Änderungen auf Item-Ebene als zeitlich geordnetes, dedupliziertes Log, bis zu 24 Stunden aufbewahrt.
- Du wählst, was jeder Record trägt über
StreamViewType: nur Keys, das neue Image, das alte Image oder beide, alt und neu. - Records sind innerhalb eines Partition Key geordnet, und ein Stream ist genauso geshardet wie die Tabelle.
- Der native Consumer ist Lambda — ein Trigger, der pro Batch neuer Records läuft, mit Kinesis Data Streams als Alternative für reichhaltigeres Fan-out.
Das Problem: reagieren ohne Polling
Du brauchst "alarmiere mich, wenn ein role.granted-Event geschrieben wird". Der
naive Ansatz ist ein geplanter Job, der jede Minute nach neuen Events scannt — was
jedes Mal die gesamte jüngste Partition liest, Kapazität kostet und immer
mindestens eine Minute zu spät ist.
Was du eigentlich willst, ist ein Push: DynamoDB sagt dir den Moment, in dem sich ein Item ändert. Genau das liefert Streams, mit dem Change-Record, der an deinen Code zugestellt wird, statt dass du ihn aufspüren musst.
Wie Streams funktioniert
Laut den AWS-Docs speichert DynamoDB Streams "ein dedupliziertes, zeitlich geordnetes Log von Änderungen für bis zu 24 Stunden" mit nativer Lambda-Integration (change data capture for DynamoDB). Jeder Record beschreibt eine Modifikation auf Item-Ebene.
Wenn du einen Stream aktivierst, wählst du einen StreamViewType, der steuert,
wie viel des geänderten Items jeder Record trägt:
| StreamViewType | each record contains |
|---|---|
| KEYS_ONLY | only the key attributes of the changed item |
| NEW_IMAGE | the entire item as it looks after the change |
| OLD_IMAGE | the entire item as it looked before the change |
| NEW_AND_OLD_IMAGES | both the before and after images |
Records sind innerhalb jedes Partition Key geordnet und der Stream ist entlang derselben Partitionsstruktur wie die Tabelle geshardet. Die Aufbewahrung beträgt 24 Stunden — Streams ist ein Reaktionspuffer, keine dauerhafte Historie. Für eine beständige Historie speicherst du die Events selbst (was genau das ist, was unsere audit-log-Tabelle bereits ist).
Der native Consumer ist ein Lambda-Trigger: DynamoDB ruft deine Funktion mit einem Batch neuer Stream-Records auf, sobald sie eintreffen.
Ein durchgespieltes Beispiel: Alert bei sensiblen Audit-Events
Die audit-log-Tabelle bekommt einen Stream mit NEW_IMAGE, sodass jeder Record das
vollständige neue Event trägt. Eine Lambda konsumiert den Batch und leitet nur die
Records weiter, die zählen:
| stream record (NEW_IMAGE) | consumer action | ||
|---|---|---|---|
| TENANT#acme | EVENT#…#a2 | action=invoice.export | send to SIEM |
| TENANT#globex EVENT#…#b9 action=role.granted | page on-call | ||
| TENANT#acme | EVENT#…#a1 | action=login.success | ignore |
Die Funktion fasst die Tabelle nie an — sie reagiert rein auf das, was der Stream ihr übergibt. Kein Polling, kein Scan, und der Alert feuert innerhalb von Sekunden nach dem Write. Weil Records pro Partition Key geordnet sind, treffen alle Events eines Tenants in der Reihenfolge ein, in der sie geschrieben wurden.
Das ist auch der Standardweg, um eine nachgelagerte Kopie zu pflegen: Ein Stream-Consumer kann jedes Event in OpenSearch für eine Volltext-Audit-Suche projizieren oder Counts aggregieren — alles abgeleitet aus demselben Change-Log.
In DynoTable umsetzen
Bevor du einen Stream-Consumer verdrahtest, musst du die exakte Form des Items
kennen, das deine Lambda erhalten wird — welche Attribute existieren, wie
verschachtelte Maps und Listen aussehen, was ein NEW_IMAGE-Record tatsächlich
enthalten wird.
Um ein Beispiel-Item zwischen reinem JSON und der Attribute-Value-Form, die ein
Stream-Record nutzt, zu konvertieren, erledigt das der
DynamoDB JSON Converter in deinem Browser. Und in
DynoTable kannst du das vollständige Item inspizieren — inklusive seiner
DynamoDB-JSON-Form — sodass du den NEW_IMAGE-Record gegen echte Daten modellierst,
statt die Feldform zu raten.

Wenn du einen Consumer lokal testest, betreibe die Tabelle gegen DynamoDB Local und inspiziere sie auf die gleiche Weise — siehe mit DynamoDB Local verbinden.
Fallstricke und nächste Schritte
- 24 Stunden sind kein Backlog. Wenn dein Consumer einen Tag lang ausfällt, altern die Records aus und sind weg. Streams ist für Reaktion nahezu in Echtzeit, nicht für beständiges Replay — bewahre die Events selbst für die Historie auf.
- Wähle den kleinsten
StreamViewType, den du brauchst.NEW_AND_OLD_IMAGESverdoppelt den Payload; wenn du nur den Key brauchst, um das Item neu zu lesen, istKEYS_ONLYgünstiger. - Ordnung ist pro Partition Key, nicht global. Events für zwei verschiedene Tenants haben untereinander keine Ordnungsgarantie — nur innerhalb der Partition eines Tenants.
- TTL-Deletes tauchen als Stream-Records auf mit dem System-Attribut-Marker, was der Weg ist, ablaufende Items zu archivieren — siehe DynamoDB TTL.
Streams macht aus dem Audit-Log eine Event-Quelle. Die nächste betriebliche Sorge ist das andere Ende der Lebensdauer eines Items — alte Events automatisch ablaufen lassen mit DynamoDB TTL.
DynoTable herunterladen, um die exakte Item-Form zu inspizieren, die dein Stream-Consumer erhalten wird, bevor du eine Zeile Lambda-Code schreibst.


