<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Event-Driven on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/event-driven/</link><description>Recent content in Event-Driven on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 06 Sep 2026 09:56:16 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/event-driven/index.xml" rel="self" type="application/rss+xml"/><item><title>Choreography vs Orchestration: Who Drives the Workflow</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-choreography-vs-orchestration-who-drives-the-workflow/</link><pubDate>Sun, 06 Sep 2026 09:56:16 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-choreography-vs-orchestration-who-drives-the-workflow/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Both patterns coordinate a multi-step business process across independent services, but they differ in where the coordination logic lives. In &lt;strong class="kw"&gt;choreography&lt;/strong&gt;, each service reacts to events and decides its own next move with no central brain; in &lt;strong class="kw"&gt;orchestration&lt;/strong&gt;, a dedicated controller tells every service what to do and in what order.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;defs&gt;&lt;marker id="arrowA" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 Z" style="fill:var(--compare-a)"/&gt;&lt;/marker&gt;&lt;marker id="arrowB" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 Z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;line x1="320" y1="20" x2="320" y2="340" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4,4"/&gt;&lt;text x="150" y="30" text-anchor="middle" font-size="16" style="fill:var(--primary)"&gt;Choreography&lt;/text&gt;&lt;text x="480" y="30" text-anchor="middle" font-size="16" style="fill:var(--primary)"&gt;Orchestration&lt;/text&gt;&lt;rect x="50" y="140" width="90" height="40" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="95" y="164" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Order Svc&lt;/text&gt;&lt;rect x="150" y="60" width="90" height="40" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="195" y="84" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Payment Svc&lt;/text&gt;&lt;rect x="150" y="220" width="90" height="40" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="195" y="244" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Shipping Svc&lt;/text&gt;&lt;path d="M108,140 C125,112 138,100 150,90" fill="none" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;text x="140" y="105" font-size="9" style="fill:var(--secondary)"&gt;event&lt;/text&gt;&lt;path d="M235,100 C262,150 262,180 235,222" fill="none" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;text x="248" y="165" font-size="9" style="fill:var(--secondary)"&gt;event&lt;/text&gt;&lt;path d="M150,238 C110,220 90,200 95,180" fill="none" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;text x="90" y="215" font-size="9" style="fill:var(--secondary)"&gt;event&lt;/text&gt;&lt;rect x="400" y="150" width="120" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="2"/&gt;&lt;text x="460" y="174" text-anchor="middle" font-size="11" style="fill:var(--primary)"&gt;Orchestrator&lt;/text&gt;&lt;rect x="400" y="50" width="120" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="460" y="74" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Payment Svc&lt;/text&gt;&lt;rect x="340" y="230" width="100" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="390" y="254" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Order Svc&lt;/text&gt;&lt;rect x="480" y="230" width="100" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="530" y="254" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Shipping Svc&lt;/text&gt;&lt;line x1="450" y1="150" x2="450" y2="92" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;line x1="472" y1="92" x2="472" y2="150" style="stroke:var(--compare-b)" stroke-width="1" stroke-dasharray="3,3"/&gt;&lt;line x1="420" y1="190" x2="400" y2="228" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;line x1="438" y1="228" x2="445" y2="192" style="stroke:var(--compare-b)" stroke-width="1" stroke-dasharray="3,3"/&gt;&lt;line x1="500" y1="190" x2="520" y2="228" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;line x1="540" y1="228" x2="525" y2="192" style="stroke:var(--compare-b)" stroke-width="1" stroke-dasharray="3,3"/&gt;&lt;text x="150" y="340" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;no central controller&lt;/text&gt;&lt;text x="480" y="340" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;commands out, responses back&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Choreography&lt;/th&gt;
&lt;th&gt;Orchestration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Trigger&lt;/td&gt;
&lt;td&gt;Any service publishes an event when something happens&lt;/td&gt;
&lt;td&gt;A client or event calls the orchestrator to start the process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coordination logic&lt;/td&gt;
&lt;td&gt;Distributed across each service&amp;rsquo;s event handlers&lt;/td&gt;
&lt;td&gt;Centralized in one orchestrator component&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Communication style&lt;/td&gt;
&lt;td&gt;Asynchronous events broadcast to whoever is listening&lt;/td&gt;
&lt;td&gt;Explicit commands and replies directed at specific services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step sequencing&lt;/td&gt;
&lt;td&gt;Emergent from chained event subscriptions&lt;/td&gt;
&lt;td&gt;Explicitly defined as a workflow or state machine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure handling&lt;/td&gt;
&lt;td&gt;Each service listens for failure events and compensates locally&lt;/td&gt;
&lt;td&gt;Orchestrator detects failure and drives compensating transactions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adding a new step&lt;/td&gt;
&lt;td&gt;Add a listener; no existing service needs to change&lt;/td&gt;
&lt;td&gt;Update the orchestrator&amp;rsquo;s workflow definition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability&lt;/td&gt;
&lt;td&gt;Hard to see the full process; requires distributed tracing&lt;/td&gt;
&lt;td&gt;Process state is visible in one place, easy to audit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coupling&lt;/td&gt;
&lt;td&gt;Low coupling between services, higher coupling to event schema&lt;/td&gt;
&lt;td&gt;Services decoupled from each other, but coupled to the orchestrator&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Choreography spreads decision-making across services via &lt;strong class="kw"&gt;events&lt;/strong&gt;; orchestration centralizes it in a single &lt;strong class="kw"&gt;controller&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choreography scales extensibility easily but makes the overall process hard to &lt;strong class="kw"&gt;trace&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Orchestration makes the workflow explicit and easy to &lt;strong class="kw"&gt;audit&lt;/strong&gt;, at the cost of a single point of coordination.&lt;/li&gt;
&lt;li&gt;Compensation logic lives in each service under choreography, but is driven centrally under &lt;strong class="kw"&gt;orchestration&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Orchestration introduces a dependency on the &lt;strong class="kw"&gt;orchestrator&lt;/strong&gt; itself as new coupling, even as it decouples the services from each other.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Choreography&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Queue vs Event Log: Consume-Once Delivery vs Replayable Stream</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-queue-vs-event-log-consume-once-delivery-vs-replayable-strea/</link><pubDate>Sun, 06 Sep 2026 09:55:24 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-queue-vs-event-log-consume-once-delivery-vs-replayable-strea/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;A message queue and an event log both move data from producers to consumers, but they differ in what happens after a message is read. A queue treats delivery as a one-time handoff where each message is &lt;strong class="kw"&gt;consumed once&lt;/strong&gt; and then removed, while an event log keeps every event in an ordered, &lt;strong class="kw"&gt;replayable&lt;/strong&gt; sequence that multiple independent readers can consume at their own pace. This distinction drives how each handles multiple consumers, failure recovery, and historical reprocessing.&lt;/p&gt;</description></item><item><title>Lambda Architecture vs Kappa Architecture: Batch-Plus-Speed vs Single-Stream Pipelines</title><link>https://comparison.metacog.co.kr/posts/2026-08-04-lambda-architecture-vs-kappa-architecture-batch-plus-speed-v/</link><pubDate>Tue, 04 Aug 2026 05:21:28 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-04-lambda-architecture-vs-kappa-architecture-batch-plus-speed-v/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Lambda Architecture and Kappa Architecture are two patterns for building big-data pipelines that need both real-time and historical results. &lt;strong class="kw"&gt;Lambda&lt;/strong&gt; runs parallel batch and speed layers that get merged at query time, while &lt;strong class="kw"&gt;Kappa&lt;/strong&gt; pushes everything through a single, replayable stream pipeline. The choice determines how much duplicate logic you maintain and how reprocessing actually works.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;defs&gt;&lt;marker id="arrowA" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"&gt;&lt;path d="M0,0 L10,5 L0,10 z" style="fill:var(--compare-a)"/&gt;&lt;/marker&gt;&lt;marker id="arrowB" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"&gt;&lt;path d="M0,0 L10,5 L0,10 z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;line x1="320" y1="20" x2="320" y2="340" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4,4"/&gt;&lt;text x="160" y="28" text-anchor="middle" font-size="16" font-weight="bold" style="fill:var(--primary)"&gt;Lambda Architecture&lt;/text&gt;&lt;text x="480" y="28" text-anchor="middle" font-size="16" font-weight="bold" style="fill:var(--primary)"&gt;Kappa Architecture&lt;/text&gt;&lt;rect x="20" y="160" width="70" height="36" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="55" y="182" text-anchor="middle" font-size="10" style="fill:var(--content)"&gt;Data Source&lt;/text&gt;&lt;rect x="130" y="70" width="130" height="50" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="195" y="92" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Batch Layer&lt;/text&gt;&lt;text x="195" y="106" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;full recompute&lt;/text&gt;&lt;rect x="130" y="240" width="130" height="50" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="195" y="262" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Speed Layer&lt;/text&gt;&lt;text x="195" y="276" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;recent, approximate&lt;/text&gt;&lt;rect x="266" y="158" width="46" height="40" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="289" y="174" text-anchor="middle" font-size="8" style="fill:var(--content)"&gt;Serving&lt;/text&gt;&lt;text x="289" y="186" text-anchor="middle" font-size="8" style="fill:var(--content)"&gt;Layer&lt;/text&gt;&lt;line x1="92" y1="168" x2="128" y2="98" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;line x1="92" y1="188" x2="128" y2="258" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;line x1="261" y1="110" x2="267" y2="172" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;line x1="261" y1="250" x2="267" y2="186" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;line x1="313" y1="178" x2="317" y2="178" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;text x="195" y="322" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;reprocess = rerun batch job&lt;/text&gt;&lt;rect x="340" y="160" width="70" height="36" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="375" y="182" text-anchor="middle" font-size="10" style="fill:var(--content)"&gt;Event Log&lt;/text&gt;&lt;rect x="450" y="130" width="150" height="90" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="525" y="168" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Stream Processing&lt;/text&gt;&lt;text x="525" y="182" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Layer&lt;/text&gt;&lt;text x="525" y="200" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;single codebase&lt;/text&gt;&lt;line x1="411" y1="178" x2="448" y2="175" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;line x1="601" y1="175" x2="628" y2="175" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;path d="M460,220 C 420,290 380,290 358,198" fill="none" style="stroke:var(--compare-b)" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrowB)"/&gt;&lt;text x="470" y="322" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;reprocess = replay the log&lt;/text&gt;&lt;text x="316" y="195" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;query&lt;/text&gt;&lt;text x="614" y="195" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;query&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Lambda Architecture&lt;/th&gt;
&lt;th&gt;Kappa Architecture&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ingestion path&lt;/td&gt;
&lt;td&gt;Raw events are forked to both a batch store and a stream processor at once&lt;/td&gt;
&lt;td&gt;Raw events are written once to an immutable, replayable log (e.g. Kafka)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Processing model&lt;/td&gt;
&lt;td&gt;Two independent codebases — a batch job and a stream job — implement the same logic twice&lt;/td&gt;
&lt;td&gt;One stream-processing codebase handles both real-time and historical computation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Historical reprocessing&lt;/td&gt;
&lt;td&gt;The batch layer periodically recomputes results over the entire raw dataset&lt;/td&gt;
&lt;td&gt;Reprocessing means replaying the log from an earlier offset through the same stream job&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State and storage&lt;/td&gt;
&lt;td&gt;Separate batch views and speed views are maintained independently, often in different stores&lt;/td&gt;
&lt;td&gt;A single serving store is continuously updated by the stream processor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Result merging&lt;/td&gt;
&lt;td&gt;The query layer merges or reconciles batch and speed views at read time&lt;/td&gt;
&lt;td&gt;No merge step — the stream processor&amp;rsquo;s output is the only view&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consistency behavior&lt;/td&gt;
&lt;td&gt;Speed layer results are approximate until the batch layer overwrites them, so the two can disagree temporarily&lt;/td&gt;
&lt;td&gt;One computation path avoids batch/speed drift, but correctness depends entirely on the stream engine&amp;rsquo;s guarantees&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational overhead&lt;/td&gt;
&lt;td&gt;Higher — two parallel pipelines to build, deploy, and monitor, with duplicated logic&lt;/td&gt;
&lt;td&gt;Lower pipeline count, but requires a log system with long enough retention to support full replays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best-fit scenario&lt;/td&gt;
&lt;td&gt;Batch and speed logic genuinely differ, or the org already has mature batch infrastructure&lt;/td&gt;
&lt;td&gt;Team wants one canonical pipeline and has a stream engine that can absorb both live and replay traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Lambda splits ingestion across a &lt;strong class="kw"&gt;batch layer&lt;/strong&gt; and a speed layer, while Kappa sends everything through one stream.&lt;/li&gt;
&lt;li&gt;Reprocessing history in Lambda means rerunning a full batch job; in Kappa it means &lt;strong class="kw"&gt;replaying the log&lt;/strong&gt; through the same stream code.&lt;/li&gt;
&lt;li&gt;Lambda&amp;rsquo;s query layer must reconcile two separate views; Kappa exposes a single &lt;strong class="kw"&gt;serving store&lt;/strong&gt; with no merge step.&lt;/li&gt;
&lt;li&gt;Kappa&amp;rsquo;s design hinges on a durable, long-retention &lt;strong class="kw"&gt;event log&lt;/strong&gt; capable of full replays, which Lambda does not require.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Lambda Architecture&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>