Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Event-Driven Architecture on AWS with EventBridge and SQS

By Kokil Thapa | Last reviewed: August 2026

Building resilient distributed systems requires moving beyond synchronous HTTP calls that create tight coupling and single points of failure. Implementing event-driven architecture on AWS with EventBridge and SQS allows you to decouple producers from consumers, absorb traffic spikes gracefully, and isolate failures before they cascade through your entire stack. This approach is particularly valuable for Laravel and Node.js applications where background processing reliability directly impacts user experience and business operations.

For developers accustomed to traditional monolithic queues like Redis or database-backed job tables, this shift represents a fundamental change in how application components communicate. Instead of pushing jobs directly to a worker queue, you publish domain events to a central bus that routes them based on content rules. If you are currently managing infrastructure for high-traffic platforms, understanding these cloud-native primitives is essential. I often discuss these architectural transitions when consulting on Laravel API best practices, as moving heavy processing off the request cycle is usually the first step toward stability.

How does event-driven architecture on AWS with EventBridge and SQS actually work?

At its core, this architecture separates the "thing that happened" from the "thing that needs to happen next." Amazon EventBridge acts as the central nervous system, receiving events from AWS services, SaaS partners, or your own custom applications. It evaluates each event against rules and routes matching events to one or more targets. Amazon SQS serves as the shock absorber, holding messages until consumers are ready to process them safely.

ProducerLaravel / NodeEventBridgeEvent BusRule FilterSQS QueueBuffer / DLQWorkerConsumer
Core topology for event-driven architecture on AWS with EventBridge and SQS showing decoupled message flow

The critical distinction here is indirection. Your application code never addresses a specific queue URL directly when publishing business events. It puts an event onto the bus. The bus decides where it goes. This means you can add new consumers—like an analytics tracker or an email notification service—without modifying the producer code or redeploying the originating application. In my experience working on production Laravel applications, this separation prevents the "spaghetti dependency" problem where every new feature requires touching three different legacy services.

Why not just use SQS directly?

Direct SQS integration works fine for simple producer-consumer relationships. But once you have multiple consumers needing different subsets of events, or when you need to integrate AWS service events (like S3 uploads or RDS snapshots) alongside custom app events, direct coupling breaks down. EventBridge provides schema registry, archival, replay capabilities, and cross-account routing that raw SQS cannot offer. You trade a small amount of latency (typically 100–500ms additional) for massive operational flexibility.

How do you configure EventBridge rules and SQS targets correctly?

Configuration mistakes here are the most common source of silent failures. A misconfigured rule simply drops events; there is no error returned to the producer. Always validate your event pattern against real payloads using the EventBridge console's "Test event pattern" feature before deploying infrastructure-as-code.

<?php
// Laravel example: Publishing a structured event to EventBridge
use Aws\EventBridge\EventBridgeClient;

$client = new EventBridgeClient([
    'version' => 'latest',
    'region'  => env('AWS_DEFAULT_REGION', 'us-east-1'),
]);

$result = $client->putEvents([
    'Entries' => [
        [
            'Source'       => 'nepal-gift-card.order',
            'DetailType'   => 'Order Placed',
            'Detail'       => json_encode([
                'order_id'    => $order->id,
                'amount_npr'  => $order->total_npr,
                'currency'    => 'NPR',
                'customer_email' => $order->email,
                'items_count' => $order->items->count(),
            ]),
            'EventBusName' => 'custom-business-bus',
        ],
    ],
]);

// Always check FailedEntryCount
if ($result['FailedEntryCount'] > 0) {
    Log::error('EventBridge putEvents failed', [
        'entries' => $result['Entries'],
    ]);
}

On the infrastructure side, your SQS queue must have a resource-based policy explicitly allowing EventBridge to send messages. Without this, events match the rule but fail delivery silently. Here is the minimal required policy statement:

{
  "Sid": "AllowEventBridgeSendMessage",
  "Effect": "Allow",
  "Principal": {
    "Service": "events.amazonaws.com"
  },
  "Action": "sqs:SendMessage",
  "Resource": "arn:aws:sqs:us-east-1:123456789012:order-processing-queue",
  "Condition": {
    "ArnEquals": {
      "aws:SourceArn": "arn:aws:events:us-east-1:123456789012:rule/custom-business-bus/order-placed-rule"
    }
  }
}

I have debugged production systems where events were being published successfully and rules were matching correctly, yet zero messages arrived in SQS. Every time, the missing queue policy was the culprit. Always define this policy in the same CloudFormation or Terraform stack as the queue itself to prevent drift.

Setting up dead-letter queues (DLQ)

Never deploy an SQS target without a DLQ. Configure the redrive policy on your primary queue to move messages after 3–5 failed processing attempts. For EventBridge targets specifically, also configure the rule-level DLQ so that delivery failures (not just processing failures) are captured. Without both layers, transient network issues or permission problems permanently lose events.

When should you choose EventBridge over SNS or direct SQS integration?

This decision depends entirely on your routing complexity and integration requirements. Each service solves a different problem, and choosing incorrectly leads to either unnecessary cost or insufficient capability.

CriteriaEventBridgeSNSDirect SQS
Routing LogicContent-based filtering, complex patternsFan-out to many subscribers, simple filteringPoint-to-point only
AWS Service IntegrationNative (200+ services emit events)Limited (S3, SES, etc. via notifications)None (must poll or use Lambda trigger)
Cross-Account/Cross-RegionBuilt-in global event routingRequires manual subscription setupNot supported natively
Message Schema RegistryYes, with validation and versioningNoNo
Latency~100–500ms added overheadLow (~10–50ms)Lowest (direct API call)
Cost at Scale$1/million events + target invocations$0.50/million requests + data transfer$0.40/million requests
Best ForComplex workflows, multi-service orchestrationReal-time fan-out, mobile push, email triggersSimple async jobs, single consumer buffering

In practice, I default to EventBridge for any system with more than two distinct consumers or any requirement to react to AWS platform events. For simple background job queues within a single Laravel application where Redis is already available, staying with Laravel Queues backed by Redis remains simpler and faster. The cloud-native stack earns its keep when boundaries cross services, accounts, or organizational teams.

Need Async Messaging?Multiple Consumers or Routing?NoYesDirect SQSSimple JobsComplex Filtering?NoYesSNS Fan-OutReal-Time BroadcastEventBridgeSmart Routing
Decision framework for selecting the right AWS messaging service based on routing complexity

How do you handle message ordering, deduplication, and failure recovery in production?

SQS Standard queues provide at-least-once delivery with best-effort ordering. FIFO queues guarantee order and exactly-once processing but cap throughput at 3,000 messages per second (with batching). Most business event workflows tolerate occasional reordering but cannot tolerate duplicates. Design your consumers for idempotency regardless of queue type.

  • Idempotency keys: Include a unique event ID in every payload. Store processed IDs in DynamoDB or Redis with a TTL matching your visibility timeout window. Check before processing; skip if already seen.
  • Visibility timeout tuning: Set this to at least 6× your p99 processing time. If your worker takes 10 seconds typically but occasionally hits 30 seconds due to external API latency, set visibility timeout to 180 seconds minimum. Too short causes duplicate processing; too long delays retry after genuine crashes.
  • Batch size vs. concurrency: SQS supports batch receives up to 10 messages. Process batches atomically when possible, but ensure partial failure handling. If 3 of 10 messages fail, delete only the 7 successful ones and let the failed 3 return to queue.
  • Poison pill detection: Monitor the ApproximateAgeOfOldestMessage metric. Messages aging beyond your expected processing window indicate systematic failures, not transient load. Alert on this before your DLQ fills up.

On a legal-tech portal I built for document attestation workflows, we initially used Standard SQS and encountered duplicate email notifications when workers timed out during PDF generation. Switching to FIFO solved ordering but introduced throughput bottlenecks during peak submission periods. The actual fix was keeping Standard SQS but implementing proper idempotency checks against a DynamoDB table keyed by event ID. This gave us both scale and correctness without FIFO constraints.

Monitoring and observability essentials

You cannot manage what you cannot see. Enable CloudWatch metrics for both EventBridge and SQS from day one. Key metrics to alarm on include Invocations vs. FailedInvocations on EventBridge rules, NumberOfMessagesVisible trending upward on SQS (indicates consumer lag), and AgeOfOldestMessage exceeding thresholds. Create a dashboard combining these with your application-level processing latency. When debugging why events aren't flowing, check EventBridge's MatchedEvents metric first—if it's zero, your rule pattern is wrong. If it's non-zero but SentToTarget is zero, your permissions or target configuration is broken.

SQS QueuePrimary BufferWorkerProcess MessageSuccessDelete MsgFail (Retry)DLQAfter N FailsVisibility Timeout
SQS retry mechanics and dead-letter queue flow for resilient event processing

What are the real-world costs and performance trade-offs for Nepal-based teams?

Cost predictability matters enormously when billing clients in NPR or operating on fixed project budgets. EventBridge charges $1.00 per million custom events ingested plus $0.30 per million target invocations. SQS Standard charges $0.40 per million requests. For a typical mid-traffic e-commerce site processing 500,000 orders monthly with 3 downstream consumers, expect roughly $2–3/month for EventBridge and under $1 for SQS. Compare this to running dedicated EC2 instances for RabbitMQ or maintaining ElastiCache for Redis queues, which start at $15–30/month minimum before engineering time.

Latency is the real trade-off. EventBridge adds 100–500ms between publish and SQS receipt. For background tasks like sending confirmation emails, generating invoices, or updating analytics, this is irrelevant. For user-facing responses requiring sub-second feedback, keep synchronous paths separate. Use this architecture for eventual consistency workflows, not real-time UI updates.

For teams in Nepal working with international clients or serving local markets, the operational burden reduction often outweighs raw performance gains. Not having to manage message broker infrastructure, handle patching, configure clustering, or troubleshoot replication lag frees significant engineering capacity. When architecting systems for serverless Laravel deployments, EventBridge and SQS integrate naturally with Lambda consumers, eliminating server management entirely. This aligns well with the reality that many Nepal-based teams operate lean and need infrastructure that scales automatically without midnight pager alerts.

Common anti-patterns to avoid

Do not use EventBridge as a general-purpose message queue for high-throughput streaming data; that is Kinesis or MSK's domain. Do not store large payloads in events; keep events under 256KB and reference S3 objects for larger data. Do not create circular dependencies where Service A emits events consumed by Service B which emits events consumed by Service A; this creates infinite loops that burn budget rapidly. Finally, do not skip testing your event patterns with realistic data before going live. The number of production incidents caused by assuming a JSON field exists when it sometimes doesn't is embarrassingly high across the industry.

Getting Started with Event-Driven Architecture on AWS with EventBridge and SQS

Start small. Pick one asynchronous workflow in your existing application—email notifications, report generation, or third-party webhook forwarding—and migrate it to EventBridge + SQS. Measure latency, verify idempotency, set up monitoring, and validate costs before expanding. Document your event schemas early; future you will thank present you when debugging at 2 AM. If you are evaluating whether this architecture fits your current project constraints or need help designing a migration strategy from synchronous processing, reach out to discuss your specific requirements. Getting the foundation right prevents expensive rework later.

Frequently Asked Questions

It decouples services using AWS EventBridge for routing events and SQS for buffering. Producers publish state changes; consumers process them asynchronously without direct dependencies or synchronous blocking calls.

EventBridge costs $1 per million events; SQS Standard is $0.40 per million requests. A 5M-event monthly workload runs under NPR 800 (~USD 6), excluding data transfer and Lambda compute charges.

Use EventBridge for content-based filtering, schema registry, SaaS integration, or archive/replay. Choose SNS for simple fan-out to many identical subscribers where advanced routing or event persistence is unnecessary.

Attach an SQS DLQ to your EventBridge rule target via the console or CloudFormation. Set MaximumRetryAttempts to 3–5. Monitor the DLQ with CloudWatch alarms and reprocess failed messages after fixing consumer errors to prevent silent data loss in production systems.

No. EventBridge provides at-least-once delivery. Your SQS consumer must be idempotent. Use a deduplication table in DynamoDB keyed by event ID plus source timestamp. I implement this pattern on every production system to safely handle duplicate deliveries during retries or network partitions.

The EventBridge service principal needs sqs:SendMessage on the target queue. Add a resource policy on the SQS queue allowing events.amazonaws.com as principal with aws:SourceArn condition matching your specific EventBridge rule ARN. Never use wildcard principals in production environments.

Define event patterns in EventBridge rules using JSON matching on detail-type, source, or nested detail fields. Only matching events trigger the SQS target. This reduces downstream processing costs significantly. On client projects, filtering at the bus level cut Lambda invocations by 70% compared to filtering inside consumers.

SQS returns the message to the queue after visibility timeout expires. Configure a redrive policy pointing to a DLQ with maxReceiveCount of 3–5. After exhausting retries, inspect DLQ messages for root cause. Always log the original event ID and error context for debugging production failures efficiently.

Create an archive on your event bus retaining events for 1–365 days. Launch a replay targeting the same or different bus with optional event pattern filtering. Replays run asynchronously. I use archives on legal-tech portals to recover from consumer bugs without asking clients to regenerate historical transactions manually.

Yes, but only with SQS FIFO queues and EventBridge FIFO buses. Both must be explicitly configured as FIFO. Message grouping uses event bus partition keys. Standard buses and queues do not preserve order. Verify FIFO requirements early because migrating later requires recreating both resources entirely.

Enable CloudWatch metrics for Invocations, FailedInvocations, and ThrottledRules on each rule. Create alarms on FailedInvocations > 0. Also monitor SQS ApproximateNumberOfMessagesVisible and DLQ depth. I add these dashboards to every deployment so ops teams detect routing failures before users report missing notifications.

Yes. Create an API destination in EventBridge with OAuth or API key auth. Map incoming webhook payloads to custom events. Route them to SQS for reliable async processing. This eliminates building custom webhook receivers and handles retries natively, which I prefer over maintaining fragile ingress endpoints for partner integrations.

Missing DLQ configuration causes silent failures. Overly broad event patterns waste downstream compute. Forgetting SQS resource policies blocks delivery. Not enabling content-based deduplication on FIFO queues causes duplicates. Always test with real event samples in staging before production rollout to catch misconfigurations early.

It auto-discovers event structures and generates typed code bindings for Lambda or SDKs. Consumers validate against registered schemas, catching breaking changes before deployment. On projects with multiple teams publishing events, this prevented dozens of runtime errors by enforcing contracts at build time rather than discovering mismatches in production logs.

Use Lambda for bursty, short-lived processing under 15 minutes with automatic scaling. Choose ECS or EC2 for long-running tasks, heavy dependencies, or predictable baseline load. On eCommerce order workflows, I use Lambda for notifications and ECS for inventory syncs exceeding timeout limits while keeping infrastructure costs aligned with actual processing patterns.

Share this article

Quick Contact Options
Choose how you want to connect me: