Serverless

Event-Driven-Architekturen auf AWS: EventBridge, SQS und Step Functions im Produktionsbetrieb

2026-02-01 · 12 Min. Lesezeit

Event-Driven Architecture gehört zu den mächtigsten Patterns auf AWS — und zu den am häufigsten missverstandenen. Ich habe Teams beobachtet, die diesen Ansatz aus den richtigen Gründen gewählt haben (lose Kopplung, unabhängige Skalierung, Event-basierte Abrechnung) und am Ende verteilte Systeme hatten, die schwieriger zu betreiben waren als der Monolith, den sie abgelöst hatten. Ich habe aber auch Teams gesehen, die event-gesteuerte Plattformen aufgebaut haben, die täglich Millionen von Events zuverlässig verarbeiten, ohne manuellen Eingriff skalieren und Komponentenausfälle elegant überstehen.

Der Unterschied liegt fast nie an der Technologiewahl. Er liegt darin, ob das Team die grundlegenden Tradeoffs vor dem Bau verstanden hatte.

Dieser Beitrag ist ein praktischer Leitfaden für den Aufbau event-gesteuerter Systeme auf AWS, die in der Produktion funktionieren. Ich zeige anhand eines konkreten Bestellworkflows — wie man ihn bei einem mittelgroßen E-Commerce-Unternehmen findet — den vollständigen Lebenszyklus: Auswahl des richtigen AWS-Messaging-Dienstes, Entwurf von Event-Schemas, Konfiguration von Routing-Regeln, Aufbau von Lambda-Consumern, Konfiguration von Dead-Letter-Queues und End-to-End-Fehleranalyse mit X-Ray.

Die richtige Wahl: EventBridge vs. SQS vs. SNS

Das ist die Frage, die mir am häufigsten gestellt wird — und die Antwort lautet fast nie „einfach EventBridge nehmen". Jeder Dienst hat eine klare Rolle, und der Einsatz des falschen erzeugt Probleme, die sich nach dem Aufbau nur schwer beheben lassen.

EventBridge verwenden, wenn:

  • Sie inhaltsbasiertes Routing brauchen (Routing nach Payload-Feldern, nicht nur nach Topic)
  • Sie AWS-Dienste oder SaaS-Anbieter ohne Glue-Code verbinden wollen
  • Sie eine Audit-Trail- und Event-Replay-Funktion benötigen
  • Mehrere unabhängige Consumer auf dasselbe Event reagieren sollen

SQS verwenden, wenn:

  • Sie garantierte At-least-once-Zustellung an einen einzelnen Consumer brauchen
  • Sie Gegendruck benötigen — die Fähigkeit des Consumers, seine Verarbeitungsrate zu steuern
  • Sie FIFO-Reihenfolge innerhalb einer Message Group benötigen
  • Sie Arbeit für asynchrone Verarbeitung in eine Warteschlange stellen (Bildverkleinerung, E-Mail-Versand, Berichtsgenerierung)

SNS verwenden, wenn:

  • Sie Fan-out zu mehreren Endpunkten gleichzeitig brauchen (Lambda + SQS + HTTP-Endpoint)
  • Sie einfaches Publish/Subscribe ohne Routing-Logik wollen
  • Zustellgeschwindigkeit wichtiger ist als Persistenz

Das Pattern, das in der Produktion funktioniert:

In der Praxis ergänzen sich EventBridge und SQS — sie konkurrieren nicht. Das Pattern, das ich für die meisten Produktionssysteme empfehle:

  1. EventBridge als zentraler Event-Bus — Services publizieren hier Domain-Events
  2. EventBridge-Regeln leiten Events an ihre Consumer weiter
  3. SQS-Queues puffern Events vor Lambda-Consumern — das bietet Gegendruck, Retry-Pufferung und DLQ-Unterstützung
  4. Lambda konsumiert aus der SQS-Queue, verarbeitet einen Batch nach dem anderen

Das kombiniert die Routing-Flexibilität von EventBridge mit der Haltbarkeit und Consumer-Rate-Kontrolle von SQS.

DienstZustellungConsumerRoutingReplayAufbewahrung
EventBridgeAt-least-onceMehrereInhaltsbasiertJa (Archiv)Standard 24 h
SQS StandardAt-least-onceEinzelnKeinsNeinBis 14 Tage
SQS FIFOExactly-onceEinzelnKeinsNeinBis 14 Tage
SNSAt-least-onceMehrereAttributfilterNeinKeine Persistenz

Event-Schemas entwerfen, die Änderungen überstehen

Das Schema-Design ist die Entscheidung, die Sie entweder rettet oder sechs Monate nach dem Launch einholt. Ein Event-Schema ist ein Vertrag zwischen Producer und Consumer — und im Gegensatz zu API-Verträgen hat eine Schemaänderung Konsequenzen für jeden Consumer, der jemals das Event abonniert hat.

Die Prinzipien, die ich bei jedem Engagement anwende:

Prinzip 1: Events sind Fakten, keine Befehle

bestellung.aufgegeben ist ein Event (ein eingetretenes Faktum). zahlung-verarbeiten ist ein Befehl (eine Anweisung). Befehle koppeln den Producer an einen bestimmten Consumer und ein bestimmtes Verhalten. Events entkoppeln sie — der Producer weiß nicht und kümmert sich nicht darum, was die Consumer tun werden.

Prinzip 2: Genug Kontext einschließen, um Callback-Aufrufe zu vermeiden

Jedes Mal, wenn ein Consumer einen anderen Service aufrufen muss, um fehlende Informationen aus dem Event zu ergänzen, haben Sie Kopplung wiederhergestellt. Schließen Sie ein, was der Consumer braucht: nicht nur bestellId, sondern kundeId, gesamtbetrag, waehrung und die Bestellpositionen.

Prinzip 3: Schemas von Anfang an versionieren

Die EventBridge Schema Registry ist genau dafür gebaut. Registrieren Sie Ihre Event-Schemas früh — Ihr Team bekommt dann automatisch generierte Code-Bindings in Python, TypeScript, Java und Go.

# Schema-Registry für die Anwendung anlegen
aws schemas create-registry \
  --registry-name "mein-ecommerce-shop" \
  --description "Event-Schemas für das Bestellsystem"

# Initiales Schema für bestellung.aufgegeben registrieren
aws schemas create-schema \
  --registry-name "mein-ecommerce-shop" \
  --schema-name "de.meinshop.bestellungen@BestellungAufgegeben" \
  --type JSONSchemaDraft4 \
  --content '{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "BestellungAufgegeben",
    "type": "object",
    "properties": {
      "version": {"type": "string"},
      "bestellId": {"type": "string"},
      "kundeId": {"type": "string"},
      "gesamtbetrag": {"type": "number"},
      "waehrung": {"type": "string"},
      "positionen": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "produktId": {"type": "string"},
            "menge": {"type": "integer"},
            "einzelpreis": {"type": "number"}
          }
        }
      },
      "aufgegebenAm": {"type": "string", "format": "date-time"}
    },
    "required": ["version", "bestellId", "kundeId", "gesamtbetrag", "positionen", "aufgegebenAm"]
  }'

Prinzip 4: Jedem Event ein version-Feld hinzufügen

Wenn Sie eine Breaking Change vornehmen müssen, publizieren Sie vorübergehend beide Event-Versionen parallel. Consumer migrieren in eigenem Tempo. Erst wenn alle Consumer migriert haben, stellen Sie die alte Version ein.

Ein vollständiges Event-Envelope sieht so aus:

{
  "source": "de.meinshop.bestellungen",
  "detail-type": "bestellung.aufgegeben",
  "detail": {
    "version": "1.0",
    "bestellId": "best-20260201-4829",
    "kundeId": "kunde-8472",
    "gesamtbetrag": 149.95,
    "waehrung": "EUR",
    "positionen": [
      {"produktId": "prod-291", "menge": 2, "einzelpreis": 49.95},
      {"produktId": "prod-847", "menge": 1, "einzelpreis": 50.05}
    ],
    "aufgegebenAm": "2026-02-01T14:32:00Z"
  }
}

Event-Bus und Routing-Regeln aufbauen

Mit dem definierten Schema richten wir die EventBridge-Infrastruktur für den Bestellworkflow ein.

Dedizierten Event-Bus anlegen:

Der Standard-Event-Bus mischt AWS-Service-Events mit Ihren Anwendungs-Events. Verwenden Sie einen dedizierten Application Event Bus — er ist übersichtlicher, leichter zu archivieren und leichter zu auditieren.

# Anwendungs-Event-Bus anlegen
aws events create-event-bus \
  --name "ecommerce-events" \
  --description "Anwendungs-Events für die Bestellverarbeitung"

# Event-Archivierung für Replay und Debugging aktivieren
aws events create-archive \
  --archive-name "ecommerce-events-archiv" \
  --event-source-arn "arn:aws:events:eu-central-1:123456789012:event-bus/ecommerce-events" \
  --retention-days 30

Routing-Regeln für Fan-out auf SQS-Queues:

# Regel: bestellung.aufgegeben an die Zahlungs-Queue weiterleiten
aws events put-rule \
  --name "bestellung-aufgegeben-an-zahlung" \
  --event-bus-name "ecommerce-events" \
  --event-pattern '{
    "source": ["de.meinshop.bestellungen"],
    "detail-type": ["bestellung.aufgegeben"]
  }' \
  --state ENABLED

# SQS-Queue für den Zahlungsdienst anlegen
aws sqs create-queue \
  --queue-name "zahlungsverarbeitung-queue" \
  --attributes '{
    "VisibilityTimeout": "300",
    "MessageRetentionPeriod": "86400",
    "ReceiveMessageWaitTimeSeconds": "20"
  }'

# SQS-Queue als Regel-Target hinzufügen
aws events put-targets \
  --event-bus-name "ecommerce-events" \
  --rule "bestellung-aufgegeben-an-zahlung" \
  --targets '[{
    "Id": "zahlung-sqs",
    "Arn": "arn:aws:sqs:eu-central-1:123456789012:zahlungsverarbeitung-queue"
  }]'

# Dasselbe Event auch an die Lagerbestand-Queue
aws events put-rule \
  --name "bestellung-aufgegeben-an-lagerbestand" \
  --event-bus-name "ecommerce-events" \
  --event-pattern '{
    "source": ["de.meinshop.bestellungen"],
    "detail-type": ["bestellung.aufgegeben"]
  }' \
  --state ENABLED

aws events put-targets \
  --event-bus-name "ecommerce-events" \
  --rule "bestellung-aufgegeben-an-lagerbestand" \
  --targets '[{
    "Id": "lagerbestand-sqs",
    "Arn": "arn:aws:sqs:eu-central-1:123456789012:lagerbestand-reservierung-queue"
  }]'

Test-Event publizieren, um das Routing zu verifizieren:

aws events put-events \
  --entries '[{
    "EventBusName": "ecommerce-events",
    "Source": "de.meinshop.bestellungen",
    "DetailType": "bestellung.aufgegeben",
    "Detail": "{\"version\":\"1.0\",\"bestellId\":\"best-test-001\",\"kundeId\":\"kunde-8472\",\"gesamtbetrag\":149.95,\"waehrung\":\"EUR\",\"positionen\":[],\"aufgegebenAm\":\"2026-02-01T14:32:00Z\"}"
  }]'

Dead-Letter-Queues und Retry-Muster konfigurieren

Hier scheitern die meisten event-gesteuerten Systeme im Produktionsbetrieb. Happy-Path-Tests laufen problemlos, aber sobald ein Consumer eine Exception wirft, stauen sich Nachrichten in der DLQ — oder werden lautlos verworfen — und niemand bemerkt es tagelang.

Jede Lambda-Event-Source-Mapping und jede SQS-Queue braucht eine ordentlich konfigurierte DLQ. Ohne Ausnahme.

DLQ-Infrastruktur anlegen:

# DLQ für die Zahlungs-Queue anlegen
aws sqs create-queue \
  --queue-name "zahlungsverarbeitung-dlq" \
  --attributes '{
    "MessageRetentionPeriod": "1209600"
  }'

# Redrive-Policy auf der Haupt-Queue setzen (3 Versuche, dann DLQ)
aws sqs set-queue-attributes \
  --queue-url "https://sqs.eu-central-1.amazonaws.com/123456789012/zahlungsverarbeitung-queue" \
  --attributes '{
    "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:eu-central-1:123456789012:zahlungsverarbeitung-dlq\",\"maxReceiveCount\":3}"
  }'

Lambda-Event-Source-Mapping mit Bisect-on-Error:

Wenn Lambda aus SQS konsumiert und eine einzelne Nachricht einen Fehler verursacht, ist das Standardverhalten, den gesamten Batch neu zu versuchen. Eine einzelne vergiftete Nachricht kann alle anderen Nachrichten im Batch dauerhaft blockieren. Die Lösung ist BisectBatchOnFunctionError:

# Lambda-Event-Source-Mapping mit intelligentem Fehler-Handling
aws lambda create-event-source-mapping \
  --function-name zahlung-verarbeiten \
  --event-source-arn "arn:aws:sqs:eu-central-1:123456789012:zahlungsverarbeitung-queue" \
  --batch-size 10 \
  --maximum-batching-window-in-seconds 30 \
  --bisect-batch-on-function-error \
  --destination-config '{
    "OnFailure": {
      "Destination": "arn:aws:sqs:eu-central-1:123456789012:zahlungsverarbeitung-dlq"
    }
  }'

CloudWatch-Alarm auf DLQ-Tiefe:

Eine DLQ, die sich lautlos füllt, ist wertlos. Richten Sie einen Alarm ein, der bei jeder DLQ-Nachricht sofort aufmerksam macht:

aws cloudwatch put-metric-alarm \
  --alarm-name "zahlungs-dlq-nachrichten" \
  --alarm-description "Nachrichten in Zahlungs-DLQ — sofortige Untersuchung erforderlich" \
  --metric-name ApproximateNumberOfMessagesVisible \
  --namespace AWS/SQS \
  --dimensions Name=QueueName,Value=zahlungsverarbeitung-dlq \
  --statistic Maximum \
  --period 60 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --evaluation-periods 1 \
  --alarm-actions "arn:aws:sns:eu-central-1:123456789012:engineering-alerts" \
  --treat-missing-data notBreaching

Exponentielles Backoff im Lambda-Handler implementieren:

Auch mit dem SQS-Retry-Mechanismus sollten Sie Backoff innerhalb Ihrer Lambda-Funktion für transiente Fehler implementieren (Downstream-API-Rate-Limits, Datenbankverbindungslimits, vorübergehende Netzwerkprobleme):

import { SQSEvent } from 'aws-lambda';

export async function handler(event: SQSEvent): Promise<{ batchItemFailures: { itemIdentifier: string }[] }> {
  const failures: { itemIdentifier: string }[] = [];

  for (const record of event.Records) {
    try {
      await zahlungVerarbeiten(JSON.parse(record.body));
    } catch (error) {
      if (istTransienterFehler(error)) {
        // Als Fehler zurückgeben — SQS versucht es mit Backoff erneut
        failures.push({ itemIdentifier: record.messageId });
      } else {
        // Nicht-transiente Fehler: Loggen und in DLQ
        console.error('Dauerhafter Fehler für Nachricht', record.messageId, error);
        failures.push({ itemIdentifier: record.messageId });
      }
    }
  }

  return { batchItemFailures: failures };
}

function istTransienterFehler(error: unknown): boolean {
  if (error instanceof Error) {
    return error.message.includes('ThrottlingException') ||
           error.message.includes('ServiceUnavailable') ||
           error.message.includes('ETIMEDOUT');
  }
  return false;
}

Das batchItemFailures-Antwortformat ist entscheidend — es teilt SQS genau mit, welche Nachrichten fehlgeschlagen sind, sodass nur diese erneut versucht werden. Ohne dieses Format versucht SQS den gesamten Batch neu oder verwirft alle Nachrichten.

Mehrstufige Workflows mit Step Functions orchestrieren

EventBridge und SQS übernehmen das Event-Routing und die Zustellung. Wenn Sie aber eine Abfolge von Schritten koordinieren müssen — Zahlung buchen, Lagerbestand reservieren, Bestätigungs-E-Mail versenden — brauchen Sie Orchestrierung, nicht nur Choreografie.

Direktes Lambda-zu-Lambda-Chaining für mehrstufige Workflows ist einer der häufigsten Architekturirrtümer, die ich sehe. Es erzeugt eine eng gekoppelte Kette, bei der der Ausfall eines Schritts das System in einem inkonsistenten Zustand hinterlassen kann — und das Debugging erfordert das gleichzeitige Durchsuchen von Logs aus mehreren Funktionen.

Step Functions löst all das.

Standard- vs. Express-Workflows:

Workflow-TypLaufzeitAusführungsmodellAbrechnungAnwendungsfall
StandardBis 1 JahrExactly-oncePro ZustandsübergangBestellabwicklung, langläufige Geschäftsprozesse
ExpressBis 5 MinutenAt-least-oncePro Laufzeit + SpeicherHochvolumige, kurzlebige Orchestrierung

Für den Bestellworkflow — der möglicherweise stundenlang auf eine Zahlungsbestätigung wartet — verwenden Sie einen Standard-Workflow.

Die State Machine für die Bestellabwicklung anlegen:

aws stepfunctions create-state-machine \
  --name "bestellabwicklung" \
  --role-arn "arn:aws:iam::123456789012:role/stepfunctions-ausfuehrungs-rolle" \
  --type STANDARD \
  --definition '{
    "Comment": "Bestellabwicklungs-Workflow",
    "StartAt": "ZahlungVerarbeiten",
    "States": {
      "ZahlungVerarbeiten": {
        "Type": "Task",
        "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:zahlung-verarbeiten",
        "Retry": [{
          "ErrorEquals": ["Lambda.ServiceException", "Lambda.AWSLambdaException"],
          "IntervalSeconds": 2,
          "MaxAttempts": 3,
          "BackoffRate": 2.0
        }],
        "Catch": [{
          "ErrorEquals": ["ZahlungAbgelehnt"],
          "Next": "ZahlungsfehlschlagBehandeln"
        }],
        "Next": "LagerbestandReservieren"
      },
      "LagerbestandReservieren": {
        "Type": "Task",
        "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:lagerbestand-reservieren",
        "Retry": [{
          "ErrorEquals": ["States.TaskFailed"],
          "IntervalSeconds": 5,
          "MaxAttempts": 2,
          "BackoffRate": 1.5
        }],
        "Catch": [{
          "ErrorEquals": ["NichtAufLager"],
          "Next": "NichtAufLagerBehandeln"
        }],
        "Next": "BestaetigungsEmailSenden"
      },
      "BestaetigungsEmailSenden": {
        "Type": "Task",
        "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:bestaetigung-senden",
        "End": true
      },
      "ZahlungsfehlschlagBehandeln": {
        "Type": "Task",
        "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:zahlungsfehler-benachrichtigen",
        "End": true
      },
      "NichtAufLagerBehandeln": {
        "Type": "Task",
        "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:nicht-auf-lager-benachrichtigen",
        "End": true
      }
    }
  }'

State Machine von EventBridge auslösen:

# bestellung.aufgegeben-Events an Step Functions weiterleiten
aws events put-rule \
  --name "bestellung-aufgegeben-an-abwicklung" \
  --event-bus-name "ecommerce-events" \
  --event-pattern '{
    "source": ["de.meinshop.bestellungen"],
    "detail-type": ["bestellung.aufgegeben"]
  }' \
  --state ENABLED

aws events put-targets \
  --event-bus-name "ecommerce-events" \
  --rule "bestellung-aufgegeben-an-abwicklung" \
  --targets '[{
    "Id": "abwicklung-sfn",
    "Arn": "arn:aws:states:eu-central-1:123456789012:stateMachine:bestellabwicklung",
    "RoleArn": "arn:aws:iam::123456789012:role/eventbridge-sfn-rolle",
    "InputTransformer": {
      "InputPathsMap": {
        "bestellId": "$.detail.bestellId",
        "kundeId": "$.detail.kundeId",
        "gesamtbetrag": "$.detail.gesamtbetrag",
        "positionen": "$.detail.positionen"
      },
      "InputTemplate": "{\"bestellId\":<bestellId>,\"kundeId\":<kundeId>,\"gesamtbetrag\":<gesamtbetrag>,\"positionen\":<positionen>}"
    }
  }]'

End-to-End-Observability mit X-Ray

Ein event-gesteuertes System mit drei Services, EventBridge, SQS und Step Functions ist bereits komplex genug, dass die Fehlersuche über CloudWatch-Logs mühsam ist. X-Ray-Tracing verändert diese Erfahrung grundlegend — ein einzelner Trace zeigt jeden Service, den das Event durchlaufen hat, wie lange jeder Schritt gedauert hat und genau wo und warum ein Fehler aufgetreten ist.

X-Ray für alle Komponenten aktivieren:

# X-Ray für jede Lambda-Funktion aktivieren
for function in zahlung-verarbeiten lagerbestand-reservieren bestaetigung-senden; do
  aws lambda update-function-configuration \
    --function-name "$function" \
    --tracing-config Mode=Active
done

# X-Ray für die Step Functions State Machine aktivieren
aws stepfunctions update-state-machine \
  --state-machine-arn "arn:aws:states:eu-central-1:123456789012:stateMachine:bestellabwicklung" \
  --tracing-configuration enabled=true

Fehlerhafte Traces abfragen:

# Traces mit Fehlern der letzten 3 Stunden
aws xray get-trace-summaries \
  --start-time $(date -u -d '3 hours ago' +%s) \
  --end-time $(date -u +%s) \
  --filter-expression 'fault = true OR error = true' \
  --query 'TraceSummaries[*].{Id:Id,Dauer:Duration,HatFehler:HasError,HatFault:HasFault}'

Korrelations-IDs durch alle Events propagieren:

Das Bindeglied, das alles zusammenhält, ist eine Korrelations-ID, die durch jede Nachricht, jeden Log-Eintrag und jeden Trace propagiert wird. Wenn ein Kunde wegen einer fehlgeschlagenen Bestellung anruft, müssen Sie in Sekunden alle zugehörigen Log-Einträge aufrufen können.

import { tracer } from '@aws-lambda-powertools/tracer';
import { logger } from '@aws-lambda-powertools/logger';

export async function handler(event: SQSEvent) {
  for (const record of event.Records) {
    const payload = JSON.parse(record.body);
    const { bestellId } = payload.detail;

    // bestellId zu allen Traces und Logs hinzufügen
    tracer.putAnnotation('bestellId', bestellId);
    logger.appendKeys({ bestellId, correlationId: payload.correlationId });

    logger.info('Zahlung wird verarbeitet', { gesamtbetrag: payload.detail.gesamtbetrag });

    // ... Verarbeitungslogik
  }
}

Idempotenz: Die unbedingte Voraussetzung

Jeder Event-Consumer muss idempotent sein — er muss dasselbe Event mehrfach verarbeiten können und dabei dasselbe Ergebnis erzielen. In einem At-least-once-Zustellsystem wie SQS und EventBridge ist doppelte Zustellung kein Bug, sondern ein dokumentiertes Feature.

Für die Zahlungsverarbeitung bedeutet das: Prüfen, ob eine Zahlung für eine gegebene bestellId bereits existiert, bevor eine neue Buchung erstellt wird. Für die Lagerbestandsreservierung: idempotent gegen die Bestell-ID reservieren, nicht blind den Bestand dekrementieren.

Das einfachste Pattern: ein DynamoDB Conditional Write, der sicherstellt, dass ein Event genau einmal verarbeitet wird:

# Erfolgreiche Verarbeitung mit Conditional Write festhalten
aws dynamodb put-item \
  --table-name "verarbeitete-events" \
  --item '{"eventId": {"S": "best-20260201-4829"}, "verarbeitetAm": {"S": "2026-02-01T14:32:05Z"}}' \
  --condition-expression "attribute_not_exists(eventId)"

Wenn die Bedingung fehlschlägt (das Item existiert bereits), wurde das Event bereits verarbeitet — still überspringen. Wenn die Bedingung erfüllt ist, verarbeiten und in einer atomaren Operation festhalten.

Was das in der Produktion bedeutet

Ich habe ein ähnliches System für einen E-Commerce-Kunden aufgebaut, der täglich 35.000 Bestellungen verarbeitet. Nach acht Monaten im Produktionsbetrieb liegt die Fehlerrate für den Abwicklungsworkflow unter 0,02 % — und diese Fehler sind ausnahmslos legitime Geschäftsfehler (abgelehnte Zahlung, nicht auf Lager), die wie geplant durch die Step-Functions-Fehlerpfade fließen. Keine Nachricht ist verloren gegangen. Der DLQ-Alarm hat dreimal ausgelöst, jedes Mal wegen eines transienten Integrationsproblems mit dem Zahlungsanbieter, das innerhalb von Minuten behoben wurde.

Die Schlüsselentscheidungen, die das System zuverlässig machen: SQS zwischen EventBridge und Lambda (keine direkten Lambda-Trigger), BisectBatchOnFunctionError für jedes Event-Source-Mapping, DLQ-Alarme direkt an PagerDuty, X-Ray über den gesamten Stack und Idempotenz bei jedem Consumer.

Wenn Sie etwas Ähnliches aufbauen und vor dem Commit ein zweites Paar Augen auf Ihre Architektur haben wollen, buchen Sie ein kostenloses Erstgespräch. Ich prüfe Ihr Design und weise auf die Fehlermodi hin, die in Tests am schwersten zu entdecken sind.

Brauchen Sie Hilfe mit Ihrer AWS-Infrastruktur?

Buchen Sie ein kostenloses 30-Minuten-Gespräch.