We use analytics cookies.We use cookies to analyze site traffic and improve your experience.
Loading...
System Design Masterclass · Messaging Event Systems
Free preview: the first 2 parts of this 6-part lesson.
Already bought the course? Sign in to read the whole lesson.
this lesson is part of
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design courseread the rest of this lesson in
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design coursein Messaging Event Systems
This lesson is part of the full System Design Masterclass. Unlock it along with 769 other lessons for a one-time payment.
One-time payment by card or PayPal
Get Lifetime AccessOne-time payment: UPI, card or netbanking
Get Lifetime Access18 Foundation lessons are free, no payment needed. Try them now
Your system receives order data from three different sources: a web API sending JSON, a legacy ERP system sending XML, and a partner integration sending CSV files via SFTP. Three different formats, all describing the same thing, an order.
Should every downstream service understand all three formats? Absolutely not. That triples the parsing logic everywhere. Instead, you normalize. A normalizer converts messages from various source formats into a single, common format before they enter the processing pipeline.
Think of it as a universal translator. Messages arrive speaking different languages. JSON, XML, CSV, Protobuf, SOAP. The normalizer translates them all into one common language that every downstream service understands. Once normalized, the rest of the system only deals with one format.
This is one of the most practical Enterprise Integration Patterns. Any system that integrates with multiple external sources needs normalization. Without it, every consumer must handle every format, a maintenance nightmare that grows with every new integration.
The normalizer combines two patterns: a content-based router and format-specific translators.
Incoming messages (mixed formats):
JSON order → Router → JSON Translator → Common Format → Processing Queue
XML order → Router → XML Translator → Common Format → Processing Queue
CSV order → Router → CSV Translator → Common Format → Processing Queue
Step 1: Identify the format (content-based routing):
function identifyFormat(msg: RawMessage): string {
if (msg.contentType === 'application/json') return 'json';
if (msg.contentType === 'application/xml') return 'xml';
if (msg.headers['x-source'] === 'legacy-erp') return 'xml-legacy';
if (msg.contentType === 'text/csv') return 'csv';
throw new Error(`Unknown format: ${msg.contentType}`);
}
Step 2: Transform to common format:
const translators = {
'json': (raw) => ({ orderId: raw.id, amount: raw.total, ... }),
'xml': (raw) => parseXml(raw).toCommonOrder(),
'csv': (raw) => parseCsvRow(raw).toCommonOrder(),
};
function normalize(msg: RawMessage): CommonOrder {
const format = identifyFormat(msg);
return translators[format](msg.body);
}
The common format (canonical model): Define a single internal representation that captures all the information your system needs. This becomes the contract between the normalizer and every downstream consumer.
interface CommonOrder {
orderId: string;
customerId: string;
items: { sku: string; quantity: number; unitPrice: number }[];
totalAmount: number;
currency: string;
shippingAddress: Address;
placedAt: Date;
source: string; // Track where it came from
}
It is easy and good
“It is really nice and good Please join the course”