[{"data":1,"prerenderedAt":750},["ShallowReactive",2],{"tag-event-driven":3},[4],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"layout":11,"date":12,"subtitle":13,"image":14,"optimized_image":14,"category":15,"tags":16,"author":21,"paginate":7,"body":22,"_type":744,"_id":745,"_source":746,"_file":747,"_stem":748,"_extension":749},"/posts/hidden-cost-event-driven-architectures","posts",false,"","The Hidden Cost of Event-Driven Architectures","A practical look at the operational and design trade-offs behind event-driven architectures, from observability and schema evolution to retries, ordering, and ownership.","post","2025-02-15T11:00:00.000Z","What asynchronous systems trade for decoupling","/assets/img/uploads/hidden-cost-event-driven-architectures.jpg","code",[15,17,18,19,20],"architecture","distributed-systems","event-driven","microservices","jaimedearcos",{"type":23,"children":24,"toc":731},"root",[25,37,42,47,52,59,64,77,82,87,93,98,154,159,189,194,199,205,210,215,220,421,426,431,437,442,447,452,475,480,486,491,496,501,529,534,540,545,550,555,594,599,605,610,615,620,626,631,636,641,647,652,657,662,668,673,678,684,725],{"type":26,"tag":27,"props":28,"children":29},"element","blockquote",{},[30],{"type":26,"tag":31,"props":32,"children":33},"p",{},[34],{"type":35,"value":36},"text","Event-driven architecture does not remove coupling. It changes where coupling lives, how it fails, and who has to understand it when production is under pressure.",{"type":26,"tag":31,"props":38,"children":39},{},[40],{"type":35,"value":41},"Event-driven architectures are appealing for good reasons. A service can publish a fact without knowing every system that will react to it. New consumers can be added without changing the producer. Work can happen asynchronously, which can improve responsiveness and absorb bursts of traffic.",{"type":26,"tag":31,"props":43,"children":44},{},[45],{"type":35,"value":46},"That is the visible part of the trade. The less visible part appears once events become an important path for the business: a customer was charged, inventory changed, an account was activated, a shipment was delayed. At that point, the system is no longer a collection of independent services connected by a broker. It is a distributed workflow whose behavior is spread across topics, consumers, storage, retries, dashboards, and operational knowledge.",{"type":26,"tag":31,"props":48,"children":49},{},[50],{"type":35,"value":51},"The cost is not a reason to avoid events. It is a reason to adopt them deliberately.",{"type":26,"tag":53,"props":54,"children":56},"h2",{"id":55},"the-coupling-did-not-disappear",[57],{"type":35,"value":58},"The coupling did not disappear",{"type":26,"tag":31,"props":60,"children":61},{},[62],{"type":35,"value":63},"With a synchronous API, coupling is obvious. The caller knows the endpoint, the request shape, the response contract, and the fact that it must wait for an answer. This can be inconvenient, but it is easy to draw and relatively easy to trace.",{"type":26,"tag":31,"props":65,"children":66},{},[67,69,75],{"type":35,"value":68},"Events remove direct knowledge between the producer and consumer. A payment service can emit ",{"type":26,"tag":15,"props":70,"children":72},{"className":71},[],[73],{"type":35,"value":74},"PaymentCompleted",{"type":35,"value":76}," without calling an invoicing service. That is useful decoupling.",{"type":26,"tag":31,"props":78,"children":79},{},[80],{"type":35,"value":81},"However, the services are still coupled through a shared meaning. The invoice consumer must understand what a completed payment means, which fields are guaranteed, whether the event can arrive twice, and what happens if it arrives after another related event. The producer may not know the consumer exists, but both systems are now dependent on the same contract.",{"type":26,"tag":31,"props":83,"children":84},{},[85],{"type":35,"value":86},"This is semantic coupling. It is usually healthier than a web of direct calls, but it must be designed and owned. A topic name is not an architecture boundary by itself.",{"type":26,"tag":53,"props":88,"children":90},{"id":89},"a-simple-event-becomes-a-distributed-workflow",[91],{"type":35,"value":92},"A simple event becomes a distributed workflow",{"type":26,"tag":31,"props":94,"children":95},{},[96],{"type":35,"value":97},"Consider an order placement flow:",{"type":26,"tag":99,"props":100,"children":103},"pre",{"className":101,"code":102,"language":35,"meta":8,"style":8},"language-text shiki shiki-themes github-dark github-light","Order service -> OrderPlaced\nInventory service -> StockReserved\nPayment service -> PaymentAuthorized\nFulfillment service -> ShipmentRequested\nNotification service -> CustomerNotified\n",[104],{"type":26,"tag":15,"props":105,"children":106},{"__ignoreMap":8},[107,118,127,136,145],{"type":26,"tag":108,"props":109,"children":112},"span",{"class":110,"line":111},"line",1,[113],{"type":26,"tag":108,"props":114,"children":115},{},[116],{"type":35,"value":117},"Order service -> OrderPlaced\n",{"type":26,"tag":108,"props":119,"children":121},{"class":110,"line":120},2,[122],{"type":26,"tag":108,"props":123,"children":124},{},[125],{"type":35,"value":126},"Inventory service -> StockReserved\n",{"type":26,"tag":108,"props":128,"children":130},{"class":110,"line":129},3,[131],{"type":26,"tag":108,"props":132,"children":133},{},[134],{"type":35,"value":135},"Payment service -> PaymentAuthorized\n",{"type":26,"tag":108,"props":137,"children":139},{"class":110,"line":138},4,[140],{"type":26,"tag":108,"props":141,"children":142},{},[143],{"type":35,"value":144},"Fulfillment service -> ShipmentRequested\n",{"type":26,"tag":108,"props":146,"children":148},{"class":110,"line":147},5,[149],{"type":26,"tag":108,"props":150,"children":151},{},[152],{"type":35,"value":153},"Notification service -> CustomerNotified\n",{"type":26,"tag":31,"props":155,"children":156},{},[157],{"type":35,"value":158},"The diagram looks pleasantly modular. In reality, every arrow creates questions:",{"type":26,"tag":160,"props":161,"children":162},"ul",{},[163,169,174,179,184],{"type":26,"tag":164,"props":165,"children":166},"li",{},[167],{"type":35,"value":168},"What happens when stock is reserved but payment is declined?",{"type":26,"tag":164,"props":170,"children":171},{},[172],{"type":35,"value":173},"Can a shipment request be processed before the payment authorization is visible?",{"type":26,"tag":164,"props":175,"children":176},{},[177],{"type":35,"value":178},"How long may the customer wait before the order status becomes accurate?",{"type":26,"tag":164,"props":180,"children":181},{},[182],{"type":35,"value":183},"Which service compensates an earlier action when a later one fails?",{"type":26,"tag":164,"props":185,"children":186},{},[187],{"type":35,"value":188},"Where does support look when an order is stuck between two steps?",{"type":26,"tag":31,"props":190,"children":191},{},[192],{"type":35,"value":193},"The workflow has become asynchronous and distributed. There is no single transaction manager, no single stack trace, and often no single database that can answer what happened. The architecture has moved coordination out of a request handler and into the behavior of many independent processes.",{"type":26,"tag":31,"props":195,"children":196},{},[197],{"type":35,"value":198},"That can be exactly the right decision. It is also real complexity, not an implementation detail to be hidden behind a message broker.",{"type":26,"tag":53,"props":200,"children":202},{"id":201},"delivery-guarantees-are-an-application-concern",[203],{"type":35,"value":204},"Delivery guarantees are an application concern",{"type":26,"tag":31,"props":206,"children":207},{},[208],{"type":35,"value":209},"Teams often describe a broker as providing \"exactly once\" processing. In practice, that statement is rarely enough to make a business action exactly once.",{"type":26,"tag":31,"props":211,"children":212},{},[213],{"type":35,"value":214},"A consumer can receive a message, write to its database, and crash before acknowledging it. The broker will deliver the message again. This is the correct behavior for at-least-once delivery, but the consumer must be prepared for it.",{"type":26,"tag":31,"props":216,"children":217},{},[218],{"type":35,"value":219},"An idempotent consumer treats repeated delivery as harmless. For example, it can store the event identifier alongside the resulting state change and reject a duplicate in the same database transaction:",{"type":26,"tag":99,"props":221,"children":225},{"className":222,"code":223,"language":224,"meta":8,"style":8},"language-java shiki shiki-themes github-dark github-light","@Transactional\npublic void handle(PaymentCompleted event) {\n    if (processedEvents.existsById(event.id())) {\n        return;\n    }\n\n    invoiceRepository.markPaid(event.orderId(), event.completedAt());\n    processedEvents.save(new ProcessedEvent(event.id()));\n}\n","java",[226],{"type":26,"tag":15,"props":227,"children":228},{"__ignoreMap":8},[229,244,268,301,314,322,332,370,412],{"type":26,"tag":108,"props":230,"children":231},{"class":110,"line":111},[232,238],{"type":26,"tag":108,"props":233,"children":235},{"style":234},"--shiki-default:#E1E4E8;--shiki-light:#24292E",[236],{"type":35,"value":237},"@",{"type":26,"tag":108,"props":239,"children":241},{"style":240},"--shiki-default:#F97583;--shiki-light:#D73A49",[242],{"type":35,"value":243},"Transactional\n",{"type":26,"tag":108,"props":245,"children":246},{"class":110,"line":120},[247,252,257,263],{"type":26,"tag":108,"props":248,"children":249},{"style":240},[250],{"type":35,"value":251},"public",{"type":26,"tag":108,"props":253,"children":254},{"style":240},[255],{"type":35,"value":256}," void",{"type":26,"tag":108,"props":258,"children":260},{"style":259},"--shiki-default:#B392F0;--shiki-light:#6F42C1",[261],{"type":35,"value":262}," handle",{"type":26,"tag":108,"props":264,"children":265},{"style":234},[266],{"type":35,"value":267},"(PaymentCompleted event) {\n",{"type":26,"tag":108,"props":269,"children":270},{"class":110,"line":129},[271,276,281,286,291,296],{"type":26,"tag":108,"props":272,"children":273},{"style":240},[274],{"type":35,"value":275},"    if",{"type":26,"tag":108,"props":277,"children":278},{"style":234},[279],{"type":35,"value":280}," (processedEvents.",{"type":26,"tag":108,"props":282,"children":283},{"style":259},[284],{"type":35,"value":285},"existsById",{"type":26,"tag":108,"props":287,"children":288},{"style":234},[289],{"type":35,"value":290},"(event.",{"type":26,"tag":108,"props":292,"children":293},{"style":259},[294],{"type":35,"value":295},"id",{"type":26,"tag":108,"props":297,"children":298},{"style":234},[299],{"type":35,"value":300},"())) {\n",{"type":26,"tag":108,"props":302,"children":303},{"class":110,"line":138},[304,309],{"type":26,"tag":108,"props":305,"children":306},{"style":240},[307],{"type":35,"value":308},"        return",{"type":26,"tag":108,"props":310,"children":311},{"style":234},[312],{"type":35,"value":313},";\n",{"type":26,"tag":108,"props":315,"children":316},{"class":110,"line":147},[317],{"type":26,"tag":108,"props":318,"children":319},{"style":234},[320],{"type":35,"value":321},"    }\n",{"type":26,"tag":108,"props":323,"children":325},{"class":110,"line":324},6,[326],{"type":26,"tag":108,"props":327,"children":329},{"emptyLinePlaceholder":328},true,[330],{"type":35,"value":331},"\n",{"type":26,"tag":108,"props":333,"children":335},{"class":110,"line":334},7,[336,341,346,350,355,360,365],{"type":26,"tag":108,"props":337,"children":338},{"style":234},[339],{"type":35,"value":340},"    invoiceRepository.",{"type":26,"tag":108,"props":342,"children":343},{"style":259},[344],{"type":35,"value":345},"markPaid",{"type":26,"tag":108,"props":347,"children":348},{"style":234},[349],{"type":35,"value":290},{"type":26,"tag":108,"props":351,"children":352},{"style":259},[353],{"type":35,"value":354},"orderId",{"type":26,"tag":108,"props":356,"children":357},{"style":234},[358],{"type":35,"value":359},"(), event.",{"type":26,"tag":108,"props":361,"children":362},{"style":259},[363],{"type":35,"value":364},"completedAt",{"type":26,"tag":108,"props":366,"children":367},{"style":234},[368],{"type":35,"value":369},"());\n",{"type":26,"tag":108,"props":371,"children":373},{"class":110,"line":372},8,[374,379,384,389,394,399,403,407],{"type":26,"tag":108,"props":375,"children":376},{"style":234},[377],{"type":35,"value":378},"    processedEvents.",{"type":26,"tag":108,"props":380,"children":381},{"style":259},[382],{"type":35,"value":383},"save",{"type":26,"tag":108,"props":385,"children":386},{"style":234},[387],{"type":35,"value":388},"(",{"type":26,"tag":108,"props":390,"children":391},{"style":240},[392],{"type":35,"value":393},"new",{"type":26,"tag":108,"props":395,"children":396},{"style":259},[397],{"type":35,"value":398}," ProcessedEvent",{"type":26,"tag":108,"props":400,"children":401},{"style":234},[402],{"type":35,"value":290},{"type":26,"tag":108,"props":404,"children":405},{"style":259},[406],{"type":35,"value":295},{"type":26,"tag":108,"props":408,"children":409},{"style":234},[410],{"type":35,"value":411},"()));\n",{"type":26,"tag":108,"props":413,"children":415},{"class":110,"line":414},9,[416],{"type":26,"tag":108,"props":417,"children":418},{"style":234},[419],{"type":35,"value":420},"}\n",{"type":26,"tag":31,"props":422,"children":423},{},[424],{"type":35,"value":425},"This example is intentionally small. In a real system, you also need to decide retention for processed identifiers, how the event key is chosen, and how an external side effect such as sending an email is made safe to repeat. A database transaction cannot automatically make an email provider, payment gateway, or third-party API idempotent.",{"type":26,"tag":31,"props":427,"children":428},{},[429],{"type":35,"value":430},"The important point is that reliable delivery changes application design. It is not something infrastructure can fully solve on its own.",{"type":26,"tag":53,"props":432,"children":434},{"id":433},"ordering-is-usually-narrower-than-expected",[435],{"type":35,"value":436},"Ordering is usually narrower than expected",{"type":26,"tag":31,"props":438,"children":439},{},[440],{"type":35,"value":441},"People often assume that events will be processed in the order in which they occurred. That may be true only within one partition, for one key, and while a consumer group is behaving normally. It is not a global promise.",{"type":26,"tag":31,"props":443,"children":444},{},[445],{"type":35,"value":446},"An account update and an account closure can be published seconds apart and still be observed in a different order by downstream systems. Retries can make an old event arrive after a newer one. A replay can introduce historical facts into a live stream.",{"type":26,"tag":31,"props":448,"children":449},{},[450],{"type":35,"value":451},"Consumers should therefore define the ordering they require rather than relying on the order they happen to observe. Common strategies include:",{"type":26,"tag":160,"props":453,"children":454},{},[455,460,465,470],{"type":26,"tag":164,"props":456,"children":457},{},[458],{"type":35,"value":459},"Partitioning by aggregate identifier when operations for one aggregate must be sequential.",{"type":26,"tag":164,"props":461,"children":462},{},[463],{"type":35,"value":464},"Including a version or sequence number in the event and ignoring stale updates.",{"type":26,"tag":164,"props":466,"children":467},{},[468],{"type":35,"value":469},"Making transitions explicit, so invalid state changes can be detected rather than silently accepted.",{"type":26,"tag":164,"props":471,"children":472},{},[473],{"type":35,"value":474},"Using a synchronous interaction when an immediate, authoritative answer is genuinely required.",{"type":26,"tag":31,"props":476,"children":477},{},[478],{"type":35,"value":479},"There is a useful design question here: does this operation need an ordered event stream, or does it need a transaction? Those are not interchangeable needs.",{"type":26,"tag":53,"props":481,"children":483},{"id":482},"schema-evolution-is-a-long-term-contract",[484],{"type":35,"value":485},"Schema evolution is a long-term contract",{"type":26,"tag":31,"props":487,"children":488},{},[489],{"type":35,"value":490},"An event is often treated as a private implementation detail because it is emitted by one service. Once another service consumes it, the event becomes a public contract, even if it never leaves the company.",{"type":26,"tag":31,"props":492,"children":493},{},[494],{"type":35,"value":495},"Adding a field is usually easy. Renaming a field, changing a value's meaning, changing a default, or splitting one event into two can break consumers in ways that are hard to spot before deployment. The producer may be healthy while a less frequently used consumer quietly falls behind.",{"type":26,"tag":31,"props":497,"children":498},{},[499],{"type":35,"value":500},"Schema management needs an explicit policy. At a minimum:",{"type":26,"tag":160,"props":502,"children":503},{},[504,509,514,519,524],{"type":26,"tag":164,"props":505,"children":506},{},[507],{"type":35,"value":508},"Define which changes are backward compatible.",{"type":26,"tag":164,"props":510,"children":511},{},[512],{"type":35,"value":513},"Version intentionally when meaning changes, not only when serialization fails.",{"type":26,"tag":164,"props":515,"children":516},{},[517],{"type":35,"value":518},"Keep events focused on facts that happened, rather than leaking a producer's internal data model.",{"type":26,"tag":164,"props":520,"children":521},{},[522],{"type":35,"value":523},"Test producer and consumer compatibility as part of delivery.",{"type":26,"tag":164,"props":525,"children":526},{},[527],{"type":35,"value":528},"Give consumers time and a migration path when a contract must change.",{"type":26,"tag":31,"props":530,"children":531},{},[532],{"type":35,"value":533},"The cost grows with the number of consumers. That is not an argument for hiding events; it is an argument for treating them with the same care as an API.",{"type":26,"tag":53,"props":535,"children":537},{"id":536},"observability-becomes-part-of-the-product",[538],{"type":35,"value":539},"Observability becomes part of the product",{"type":26,"tag":31,"props":541,"children":542},{},[543],{"type":35,"value":544},"In a synchronous request, a trace can often show a failure from one endpoint to another. In an event-driven workflow, the result may appear minutes later in a different process after several retries. Without good observability, engineers and support teams are left correlating timestamps across logs and guessing.",{"type":26,"tag":31,"props":546,"children":547},{},[548],{"type":35,"value":549},"Every business event should carry enough context to be traced without making it a dumping ground for internal state. A correlation identifier, causation identifier, aggregate identifier, event identifier, timestamp, and schema version are a strong starting point.",{"type":26,"tag":31,"props":551,"children":552},{},[553],{"type":35,"value":554},"The technical metadata matters, but the operational view matters just as much. A useful system can answer questions such as:",{"type":26,"tag":160,"props":556,"children":557},{},[558,579,584,589],{"type":26,"tag":164,"props":559,"children":560},{},[561,563,569,571,577],{"type":35,"value":562},"How many ",{"type":26,"tag":15,"props":564,"children":566},{"className":565},[],[567],{"type":35,"value":568},"OrderPlaced",{"type":35,"value":570}," events have not produced a ",{"type":26,"tag":15,"props":572,"children":574},{"className":573},[],[575],{"type":35,"value":576},"ShipmentRequested",{"type":35,"value":578}," event within the expected time?",{"type":26,"tag":164,"props":580,"children":581},{},[582],{"type":35,"value":583},"Which consumer is retrying and why?",{"type":26,"tag":164,"props":585,"children":586},{},[587],{"type":35,"value":588},"Can a failed message be replayed safely after a fix?",{"type":26,"tag":164,"props":590,"children":591},{},[592],{"type":35,"value":593},"Which customer-facing state should support trust while the workflow is still in progress?",{"type":26,"tag":31,"props":595,"children":596},{},[597],{"type":35,"value":598},"If the answer depends on manually inspecting a broker console, the architecture is still incomplete.",{"type":26,"tag":53,"props":600,"children":602},{"id":601},"retries-need-a-destination",[603],{"type":35,"value":604},"Retries need a destination",{"type":26,"tag":31,"props":606,"children":607},{},[608],{"type":35,"value":609},"Retries are necessary because networks fail, dependencies become unavailable, and deployments interrupt work. An unbounded retry, though, turns a temporary problem into invisible queue growth or a permanent loop.",{"type":26,"tag":31,"props":611,"children":612},{},[613],{"type":35,"value":614},"A consumer should distinguish between failures that may succeed later and failures that require intervention. Transient failures can use bounded retries with backoff. Invalid payloads, missing invariants, and incompatible schemas usually need to be sent to a dead-letter path with enough context to diagnose and recover them.",{"type":26,"tag":31,"props":616,"children":617},{},[618],{"type":35,"value":619},"Recovery is a product decision as well as an engineering decision. Replay can be dangerous if handlers are not idempotent or if an event triggers external actions. A dead-letter queue is useful only when someone owns the process for inspecting, correcting, replaying, or deliberately discarding its messages.",{"type":26,"tag":53,"props":621,"children":623},{"id":622},"ownership-must-be-visible",[624],{"type":35,"value":625},"Ownership must be visible",{"type":26,"tag":31,"props":627,"children":628},{},[629],{"type":35,"value":630},"The cost of asynchronous systems is often paid by the team on call rather than the team that introduced the topic. Ownership should therefore be explicit.",{"type":26,"tag":31,"props":632,"children":633},{},[634],{"type":35,"value":635},"For each event, make it clear who owns the contract, how consumers discover changes, who maintains the schema, what service owns the business state, and who investigates a workflow that stops progressing. Shared infrastructure teams can provide a reliable platform, but they cannot decide the business meaning of an event or repair every broken consumer relationship.",{"type":26,"tag":31,"props":637,"children":638},{},[639],{"type":35,"value":640},"This is also where event catalogs, runbooks, dashboards, and service-level objectives earn their place. They are not bureaucracy around the architecture. They are the tools that make an asynchronous system understandable when its normal flow has already diverged.",{"type":26,"tag":53,"props":642,"children":644},{"id":643},"when-events-are-worth-the-cost",[645],{"type":35,"value":646},"When events are worth the cost",{"type":26,"tag":31,"props":648,"children":649},{},[650],{"type":35,"value":651},"Events are a strong fit when a fact should trigger independent reactions, when work can complete asynchronously, when the system benefits from absorbing bursts, or when the domain naturally produces a useful history of changes.",{"type":26,"tag":31,"props":653,"children":654},{},[655],{"type":35,"value":656},"They are a weaker fit when a caller needs an immediate decision, a small system only has one downstream action, or the team cannot yet support contract ownership and operational visibility. A direct call with a clear timeout and a well-defined failure response can be simpler and more reliable than a premature event pipeline.",{"type":26,"tag":31,"props":658,"children":659},{},[660],{"type":35,"value":661},"The best systems often use both. Synchronous communication establishes an immediate command or query boundary; events distribute facts that other parts of the system can process independently.",{"type":26,"tag":53,"props":663,"children":665},{"id":664},"conclusion",[666],{"type":35,"value":667},"Conclusion",{"type":26,"tag":31,"props":669,"children":670},{},[671],{"type":35,"value":672},"Event-driven architecture buys flexibility by moving coordination into contracts, consumers, and operations. The hidden cost is not the broker. It is the discipline required to make asynchronous workflows observable, recoverable, evolvable, and owned.",{"type":26,"tag":31,"props":674,"children":675},{},[676],{"type":35,"value":677},"When that discipline is present, events can make a system more resilient and easier to extend. When it is absent, they can turn straightforward business flows into a set of delayed surprises. Design the operational model at the same time as the event model, and the trade becomes a deliberate one.",{"type":26,"tag":53,"props":679,"children":681},{"id":680},"further-reading",[682],{"type":35,"value":683},"Further Reading",{"type":26,"tag":160,"props":685,"children":686},{},[687,701,713],{"type":26,"tag":164,"props":688,"children":689},{},[690,699],{"type":26,"tag":691,"props":692,"children":696},"a",{"href":693,"rel":694},"https://dataintensive.net/",[695],"nofollow",[697],{"type":35,"value":698},"Designing Data-Intensive Applications",{"type":35,"value":700},", Martin Kleppmann.",{"type":26,"tag":164,"props":702,"children":703},{},[704,711],{"type":26,"tag":691,"props":705,"children":708},{"href":706,"rel":707},"https://microservices.io/patterns/data/transactional-outbox.html",[695],[709],{"type":35,"value":710},"The Transactional Outbox Pattern",{"type":35,"value":712},", Chris Richardson.",{"type":26,"tag":164,"props":714,"children":715},{},[716,723],{"type":26,"tag":691,"props":717,"children":720},{"href":718,"rel":719},"https://kafka.apache.org/documentation/#design",[695],[721],{"type":35,"value":722},"Apache Kafka documentation: Design",{"type":35,"value":724},".",{"type":26,"tag":726,"props":727,"children":728},"style",{},[729],{"type":35,"value":730},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":8,"searchDepth":120,"depth":120,"links":732},[733,734,735,736,737,738,739,740,741,742,743],{"id":55,"depth":120,"text":58},{"id":89,"depth":120,"text":92},{"id":201,"depth":120,"text":204},{"id":433,"depth":120,"text":436},{"id":482,"depth":120,"text":485},{"id":536,"depth":120,"text":539},{"id":601,"depth":120,"text":604},{"id":622,"depth":120,"text":625},{"id":643,"depth":120,"text":646},{"id":664,"depth":120,"text":667},{"id":680,"depth":120,"text":683},"markdown","content:posts:hidden-cost-event-driven-architectures.md","content","posts/hidden-cost-event-driven-architectures.md","posts/hidden-cost-event-driven-architectures","md",1790546260139]