AWS EventBridge: serverloze gebeurtenisbus en op inhoud gebaseerde routering
Amazon EventBridge is de serverloze evenementenbus van AWS: hij routeert evenementen op basis van inhoud richting Lambda, SQS, Step Functions, API-bestemmingen en tientallen andere doelen. In tegenstelling tot SNS publiceert het niet voor alle abonnees, maar is het wel van toepassing intelligente routeringsregels op basis van de payloadvelden. Met het geïntegreerde Schema Registry worden schemafouten gedetecteerd tijdens publicatie, niet tijdens runtime.
EventBridge-architectuur: bus, regel, doel
EventBridge is georganiseerd in drie fundamentele concepten:
- Evenementenbus: het kanaal dat de gebeurtenissen ontvangt. Elk AWS-account heeft een standaard gebeurtenisbus (ontvangt gebeurtenissen van AWS-services zoals EC2, S3, RDS), meerdere aangepaste bussen (evenementenbussen op maat) voor toepassingsevenementen, bijv partner evenementenbus voor SaaS-integraties (Zendesk, Datadog, Salesforce).
- Gebeurtenisregel: een regel met a gebeurtenis patroon (JSON-filter) dat bepaalt welke gebeurtenissen naar welke doelen moeten worden gerouteerd. Eén regel kan maximaal vijf doelen hebben.
- Doel: De bestemming van de gebeurtenis. Ondersteunt Lambda, SQS, SNS, Step-functies, API Gateway, Kinesis, EventBridge Bus van andere accounts en meer dan 20 andere bestemmingen.
Structuur van een EventBridge-evenement
{
"version": "0",
"id": "12345678-1234-1234-1234-123456789012",
"source": "com.mioapp.ordini",
"account": "123456789012",
"time": "2026-03-20T10:30:00Z",
"region": "eu-west-1",
"detail-type": "OrdineEffettuato",
"detail": {
"ordineId": "ord-abc123",
"clienteId": "cli-xyz789",
"totale": 149.99,
"stato": "IN_ATTESA_PAGAMENTO",
"categoria": "ELETTRONICA"
}
}
Het veld detail bevat de payload van de toepassing. source e detail-type identificeer het type evenement.
Publiceer evenementen op EventBridge
// EventBridgePublisher.java - Pubblica eventi custom su EventBridge
import software.amazon.awssdk.services.eventbridge.EventBridgeClient;
import software.amazon.awssdk.services.eventbridge.model.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
public class EventBridgePublisher {
private final EventBridgeClient eventBridgeClient;
private final ObjectMapper objectMapper;
private static final String EVENT_BUS_NAME = "mioapp-production";
public EventBridgePublisher() {
this.eventBridgeClient = EventBridgeClient.builder()
.region(Region.EU_WEST_1)
.build();
this.objectMapper = new ObjectMapper();
}
public void publishOrdineEffettuato(OrdineEffettuatoEvent event) throws Exception {
String detailJson = objectMapper.writeValueAsString(event);
PutEventsRequestEntry entry = PutEventsRequestEntry.builder()
.source("com.mioapp.ordini")
.detailType("OrdineEffettuato")
.detail(detailJson)
.eventBusName(EVENT_BUS_NAME)
// TraceHeader per X-Ray distributed tracing (opzionale)
.traceHeader("Root=1-63441c4a-abcdef")
.build();
PutEventsResponse response = eventBridgeClient.putEvents(
PutEventsRequest.builder()
.entries(entry)
.build()
);
if (response.failedEntryCount() > 0) {
response.entries().forEach(e -> {
if (e.errorCode() != null) {
throw new EventPublishException(
"Errore pubblicazione evento: " + e.errorCode() + " - " + e.errorMessage()
);
}
});
}
}
// Batch publish (max 10 eventi per chiamata, 256 KB totale)
public void publishBatch(List<DomainEvent> events) throws Exception {
List<PutEventsRequestEntry> entries = new ArrayList<>();
for (DomainEvent event : events) {
entries.add(PutEventsRequestEntry.builder()
.source("com.mioapp." + event.getAggregateType())
.detailType(event.getClass().getSimpleName())
.detail(objectMapper.writeValueAsString(event))
.eventBusName(EVENT_BUS_NAME)
.build());
}
PutEventsResponse response = eventBridgeClient.putEvents(
PutEventsRequest.builder()
.entries(entries)
.build()
);
System.out.printf("Pubblicati %d/%d eventi. Falliti: %d%n",
entries.size() - response.failedEntryCount(),
entries.size(),
response.failedEntryCount());
}
}
Gebeurtenispatronen: op inhoud gebaseerde routering
Het hart van EventBridge is de op inhoud gebaseerde routering: regelsfilter gebeurtenissen op basis van de inhoud van de JSON-payload, niet alleen op het gebeurtenistype. Patronen ondersteunen matching op voorvoegsels, achtervoegsels, specifieke waarden, numerieke bereiken en negatieve voorwaarden.
# Esempi di Event Pattern per il routing
# Pattern 1: Tutti gli ordini di importo alto (sopra 500 EUR)
{
"source": ["com.mioapp.ordini"],
"detail-type": ["OrdineEffettuato"],
"detail": {
"totale": [{ "numeric": [">", 500] }]
}
}
# Pattern 2: Ordini con prodotti della categoria ELETTRONICA o GAMING
{
"source": ["com.mioapp.ordini"],
"detail-type": ["OrdineEffettuato"],
"detail": {
"categoria": ["ELETTRONICA", "GAMING"]
}
}
# Pattern 3: Ordini di clienti premium con pagamento completato
{
"source": ["com.mioapp.ordini"],
"detail-type": ["OrdineEffettuato", "PagamentoConfermato"],
"detail": {
"tipoCliente": ["PREMIUM", "VIP"],
"stato": [{ "prefix": "PAGA" }]
}
}
# Pattern 4: Qualsiasi evento di errore da tutti i servizi dell'app
{
"source": [{ "prefix": "com.mioapp." }],
"detail-type": [{ "suffix": "Failed" }]
}
# Pattern 5: Esclusione (not): tutti gli ordini ECCETTO i test
{
"source": ["com.mioapp.ordini"],
"detail-type": ["OrdineEffettuato"],
"detail": {
"ambiente": [{ "anything-but": ["test", "staging"] }]
}
}
Maak een regel met CloudFormation / Terraform
# Terraform: event bus, rule e target Lambda
# Custom Event Bus
resource "aws_cloudwatch_event_bus" "mioapp" {
name = "mioapp-production"
}
# Rule: ordini ad alto valore verso Lambda di VIP handling
resource "aws_cloudwatch_event_rule" "ordini_vip" {
name = "ordini-vip-handler"
event_bus_name = aws_cloudwatch_event_bus.mioapp.name
event_pattern = jsonencode({
source = ["com.mioapp.ordini"]
detail-type = ["OrdineEffettuato"]
detail = {
totale = [{ numeric = [">", 500] }]
tipoCliente = ["PREMIUM", "VIP"]
}
})
description = "Instrada ordini VIP alto valore alla Lambda dedicata"
}
# Target: Lambda VIP handler
resource "aws_cloudwatch_event_target" "ordini_vip_lambda" {
rule = aws_cloudwatch_event_rule.ordini_vip.name
event_bus_name = aws_cloudwatch_event_bus.mioapp.name
arn = aws_lambda_function.vip_handler.arn
# Retry policy per il target
retry_policy {
maximum_event_age_in_seconds = 3600 # 1 ora
maximum_retry_attempts = 3
}
# Dead letter queue per gli eventi che non vengono consegnati
dead_letter_config {
arn = aws_sqs_queue.eventbridge_dlq.arn
}
}
# Rule: tutti gli errori verso SQS per analisi
resource "aws_cloudwatch_event_rule" "tutti_errori" {
name = "tutti-errori-sqs"
event_bus_name = aws_cloudwatch_event_bus.mioapp.name
event_pattern = jsonencode({
source = [{ prefix = "com.mioapp." }]
detail-type = [{ suffix = "Failed" }]
})
}
resource "aws_cloudwatch_event_target" "errori_sqs" {
rule = aws_cloudwatch_event_rule.tutti_errori.name
event_bus_name = aws_cloudwatch_event_bus.mioapp.name
arn = aws_sqs_queue.errori_queue.arn
}
Schemaregister en schemadetectie
EventBridge bevat er één Schemaregister ingebouwd: kan automatisch ontdekken de patronen van de gebeurtenissen die op de bus passeren (ontdekkingsschema) en volhard de definities van een schema voor validatie en codegeneratie.
Het belangrijkste voordeel is de code genereren: uitgaande van het ontdekte schema, EventBridge genereert automatisch Java-, TypeScript- of Python-klassen die overeenkomen met de payload van de gebeurtenis.
# Abilitare schema discovery su un event bus (AWS CLI)
aws schemas create-discoverer \
--source-arn arn:aws:events:eu-west-1:123456789012:event-bus/mioapp-production \
--description "Auto-discovery per mioapp-production"
# Elencare gli schemi scoperti
aws schemas list-schemas \
--registry-name discovered-schemas
# Scaricare il codice generato per Java
aws schemas get-code-binding-source \
--registry-name discovered-schemas \
--schema-name "com.mioapp.ordini@OrdineEffettuato" \
--language "java8" \
--schema-version "1" \
--output text > OrdineEffettuatoEvent.java
Evenementarchief en herhaling
Een van de krachtigste functies van EventBridge is deEvenementenarchief: archiveert automatisch alle gebeurtenissen die in de bus plaatsvinden gedurende een configureerbare periode, het toestaan van de opnieuw afspelen van gebeurtenissen uit het verleden (handig voor het opnieuw opbouwen van projecties, het debuggen van productieproblemen of het testen van nieuwe consumenten).
# Creare un archivio per il bus degli ordini
aws events create-archive \
--archive-name mioapp-ordini-archive \
--event-source-arn arn:aws:events:eu-west-1:123456789012:event-bus/mioapp-production \
--retention-days 90 \
--event-pattern '{
"source": ["com.mioapp.ordini"],
"detail-type": ["OrdineEffettuato", "PagamentoConfermato"]
}'
# Replay degli eventi archiviati (utile per rebuild di read model)
aws events start-replay \
--replay-name rebuild-read-model-20260320 \
--event-source-arn arn:aws:events:eu-west-1:123456789012:archive/mioapp-ordini-archive \
--event-start-time "2026-01-01T00:00:00Z" \
--event-end-time "2026-03-20T23:59:59Z" \
--destination '{
"Arn": "arn:aws:events:eu-west-1:123456789012:event-bus/mioapp-production",
"FilterArns": [
"arn:aws:events:eu-west-1:123456789012:rule/mioapp-production/ordini-vip-handler"
]
}'
# Monitorare il replay
aws events describe-replay \
--replay-name rebuild-read-model-20260320
EventBridge Lambda-consument
// Handler Lambda Java per eventi EventBridge
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.ScheduledEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
public class OrdiniVipHandler implements RequestHandler<ScheduledEvent, String> {
private final ObjectMapper objectMapper = new ObjectMapper();
private final VipNotificationService notificationService = new VipNotificationService();
@Override
public String handleRequest(ScheduledEvent event, Context context) {
context.getLogger().log("Evento ricevuto: " + event.getDetailType());
try {
// Deserializza il detail field
OrdineEffettuatoEvent ordine = objectMapper.convertValue(
event.getDetail(),
OrdineEffettuatoEvent.class
);
context.getLogger().log(String.format(
"Ordine VIP: %s, cliente: %s, totale: %.2f",
ordine.getOrdineId(),
ordine.getClienteId(),
ordine.getTotale()
));
// Invia notifica personalizzata al cliente VIP
notificationService.sendVipOrderConfirmation(
ordine.getClienteId(),
ordine.getOrdineId(),
ordine.getTotale()
);
return "SUCCESS";
} catch (Exception e) {
context.getLogger().log("ERRORE: " + e.getMessage());
// Rilancia per triggherare il retry di EventBridge
throw new RuntimeException("Elaborazione fallita", e);
}
}
}
// TypeScript handler per Lambda Node.js
// export const handler = async (event: EventBridgeEvent<'OrdineEffettuato', OrdineDetail>) => {
// const { ordineId, clienteId, totale } = event.detail;
// await sendVipNotification(clienteId, ordineId, totale);
// return { statusCode: 200 };
// };
Best practices voor EventBridge
- Custom Event Bus voor elke omgeving: Gebruik aparte bussen voor productie, enscenering en ontwikkeling. Stuur geen testgebeurtenissen naar de productiebus.
- Gebruik altijd DLQ voor doelen: Configureer een SQS-wachtrij voor dode brieven voor elk doel om geen evenementen te missen als de consument faalt.
- Idempotentie bij Lambda-consumenten: EventBridge garandeert minimaal één keer levering. De Lambda moet dubbele ontvangst van dezelfde gebeurtenis afhandelen.
-
Versiebeheer van gebeurtenissen: Voeg altijd een veld toe
schemaVersionin de details. EventBridge heeft geen ingebouwd versiebeheermechanisme: behandel dit in de payload. - Evenementenarchief voor elke busproductie: configureer altijd een archief met retentie minimaal 30 dagen. Replay kan de redding zijn in het geval van bugs bij consumenten.
Volgende stappen in de serie
- Artikel 7 – SQS versus SNS versus EventBridge: beslissingsgids voor het kiezen voor elke specifieke use case de juiste AWS-berichtenservice.
- Artikel 8 – Dead Letter-wachtrij en veerkracht: correct configureren de DLQ voor EventBridge, SQS en Lambda om mislukte berichten af te handelen zonder gegevensverlies.
Link met andere series
- Saga-patroon (artikel 5): EventBridge is de ideale berichtenbus voor Choreography Saga op AWS: elke service publiceert evenementen op EventBridge en de anderen services reageren via de geconfigureerde routeringsregels.
- Apache Kafka (serie 38): voor on-premise of hybride systemen, Kafka en EventBridge kunnen naast elkaar bestaan: Kafka voor interne berichtenuitwisseling met hoge doorvoer, EventBridge voor integratie met externe AWS- en SaaS-diensten.







