Implementing Event-Driven Architecture in Next.js
Core Implementation Strategy
1. Node.js Event System
Use Node.js' native EventEmitter for basic event handling:
// lib/eventBus.js
import { EventEmitter } from 'events';
export const eventBus = new EventEmitter();
2. Serverless Event Routing
Key integrations:
- Upstash QStash for cross-service communication
- AWS EventBridge for complex routing
- Pusher for real-time WebSocket updates
3. Reactive Frontend
Custom hook for component communication:
// hooks/useEvent.ts
export const useEvent = <T>(eventName: string, callback: (data: T) => void) => {
const dispatch = (data: T) => window.dispatchEvent(new CustomEvent(eventName, { detail: data }));
useEffect(() => {
const handler = (e: CustomEvent<T>) => callback(e.detail);
window.addEventListener(eventName, handler as EventListener);
return () => window.removeEventListener(eventName, handler as EventListener);
}, []);
return dispatch;
};
Recommended Tool Stack
| Category | Tools | Use Case |
|---|---|---|
| Databases | Supabase, PlanetScale, NeonDB | Persistent event storage |
| Caching | Upstash Redis, Vercel KV | Event state caching |
| Messaging | QStash, AWS SNS/SQS, Pusher | Cross-service communication |
| Monitoring | Sentry, Datadog | Pipeline observability |
| State Management | Zustand, Redux Toolkit | Global state handling |
Key Implementation Patterns
1. Event Sourcing/CQRS
// pages/api/events.ts
export async function POST(req: Request) {
const event = await req.json();
await persistEvent(event);
await updateReadModel(event);
}
2. Reliable Delivery
// Serverless function handler
export default async (req, res) => {
try {
await processEvent(req.body);
await qstash.resend(req);
} catch (error) {
await deadLetterQueue.add(req.body);
}
};
3. Real-Time UI Updates
// components/RealTimeFeed.js
useEffect(() => {
const ws = new WebSocket('wss://api.your-app.com/events');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
eventBus.emit(data.type, data.payload);
};
}, []);
Best Practices
-
Event Design
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "eventId": { "type": "string" }, "timestamp": { "type": "number" } } } -
Performance Optimization
- Batch process events in serverless functions
- Use Redis streams for high-throughput scenarios
-
Observability
eventEmitter.on('user:registered', (data) => { Sentry.addBreadcrumb({ message: 'User registration event', data }); });
Example Architecture
E-Commerce Product Flow
graph LR A[Admin UI] -->|emit| B[ProductUpdatedEvent] B --> C[(Event Store)] C --> D[Search Indexer] C --> E[Email Service] C --> F[Cache Invalidation]
Implementation Features
- Next.js Admin Dashboard with QStash integration
- Serverless consumers for Algolia/Redis updates
- React frontend using
useEventhook