<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Architecture Field Notes</title><link>https://architectures.metacog.co.kr/</link><description>Recent content on Architecture Field Notes</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Thu, 20 Aug 2026 13:15:24 -0500</lastBuildDate><atom:link href="https://architectures.metacog.co.kr/index.xml" rel="self" type="application/rss+xml"/><item><title>Irreversible Decisions</title><link>https://architectures.metacog.co.kr/docs/foundations/irreversible-decisions/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/foundations/irreversible-decisions/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Someone asks &amp;ldquo;is this an architecture decision or just an implementation
detail?&amp;rdquo; The honest answer is usually a question back: &lt;strong&gt;how much would it cost
to undo in six months?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That is the only definition that has held up in practice. Not &amp;ldquo;is it drawn on
the diagram&amp;rdquo;, not &amp;ldquo;did an architect approve it&amp;rdquo;, not &amp;ldquo;does it span services&amp;rdquo;.
Cost of reversal.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Sort every decision into one of two buckets before you spend time on it.&lt;/p&gt;</description></item><item><title>Constraints First</title><link>https://architectures.metacog.co.kr/docs/foundations/constraints-first/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/foundations/constraints-first/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You get a requirements document, a ticket, or a conversation that starts with
&amp;ldquo;we need a service that…&amp;rdquo;. Whatever it says, it is describing a &lt;em&gt;solution
someone already imagined&lt;/em&gt;, not the constraints that make a solution correct.&lt;/p&gt;
&lt;p&gt;Designing against stated requirements without finding the real constraints is
the most common way to build something technically excellent and operationally
useless.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Before drawing anything, get numbers for these. Guessed numbers with an order
of magnitude are fine. No numbers is not fine.&lt;/p&gt;</description></item><item><title>Coupling and Cohesion in Practice</title><link>https://architectures.metacog.co.kr/docs/foundations/coupling-and-cohesion/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/foundations/coupling-and-cohesion/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Two things are coupled when changing one forces you to change the other. That
definition is uselessly abstract until you attach it to concrete pain: a
deployment that must be ordered, a schema change that breaks a team you have
never met, a test suite that cannot run without six containers.&lt;/p&gt;
&lt;p&gt;Every architecture pattern in existence — layering, microservices, events,
hexagonal, whatever — is an attempt to control &lt;em&gt;which&lt;/em&gt; things are coupled and
&lt;em&gt;how&lt;/em&gt;. Learning to name the coupling type is more useful than learning the
patterns.&lt;/p&gt;</description></item><item><title>Trade-off Sliders</title><link>https://architectures.metacog.co.kr/docs/foundations/trade-off-sliders/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/foundations/trade-off-sliders/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Someone proposes a design and someone else objects. The argument goes in
circles because both people are optimising for different qualities and neither
has said which one.&lt;/p&gt;
&lt;p&gt;The fix is boring and works: force the trade-off to be named out loud, in
advance, with a ranking. Not &amp;ldquo;we value all of these&amp;rdquo; — a ranking.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Pick the top three, in order, before evaluating options. Write them down. The
rest are constraints to satisfy, not goals to maximise.&lt;/p&gt;</description></item><item><title>The Boring Baseline</title><link>https://architectures.metacog.co.kr/docs/foundations/boring-baseline/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/foundations/boring-baseline/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Every new system starts with a choice you make before you notice you are making
it: how much novelty to accept. Novelty is not just new technology — it is any
component the team has not operated before, including a familiar technology
used in an unfamiliar way.&lt;/p&gt;
&lt;p&gt;Novelty has a budget. Most teams spend it on the wrong things.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The boring baseline, roughly, for a system with real users and a team under
twenty people:&lt;/p&gt;</description></item><item><title>Monolith First, Split on Evidence</title><link>https://architectures.metacog.co.kr/docs/system-design/monolith-first/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/system-design/monolith-first/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A new system, a small team, and a strong instinct that &amp;ldquo;we should build it as
microservices so it scales.&amp;rdquo; The instinct conflates two different kinds of
scale: &lt;strong&gt;load scale&lt;/strong&gt; and &lt;strong&gt;organisational scale&lt;/strong&gt;. Microservices help with the
second. They rarely help with the first, and they actively hurt it at small
sizes by adding network hops to what used to be function calls.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Start with a modular monolith. One deployable, one datastore, clear internal
module boundaries enforced by package structure, build rules, or a linter.&lt;/p&gt;</description></item><item><title>Service Boundaries That Survive Reorgs</title><link>https://architectures.metacog.co.kr/docs/system-design/service-boundaries/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/system-design/service-boundaries/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You have decided to split. Now the question is &lt;em&gt;where&lt;/em&gt;, and most teams answer
it by looking at the domain model and putting a service around each noun. User
service, Order service, Product service, Notification service.&lt;/p&gt;
&lt;p&gt;This produces boundaries that look tidy on a diagram and generate constant
cross-service chatter in production, because business operations do not respect
noun boundaries.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Draw the boundary where three things line up:&lt;/p&gt;</description></item><item><title>Synchronous vs Asynchronous Integration</title><link>https://architectures.metacog.co.kr/docs/system-design/sync-vs-async/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/system-design/sync-vs-async/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Service A needs something from service B. HTTP call, or a message on a broker?
This gets argued as a philosophy question (&amp;ldquo;event-driven architecture&amp;rdquo;) when it
is actually a question with a mechanical answer.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Ask what the caller does while waiting.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the caller cannot proceed without the answer and a human is waiting →
&lt;strong&gt;synchronous&lt;/strong&gt;. A user staring at a spinner needs a response, and hiding a
request-response interaction behind a queue just means you rebuilt
request-response badly, with correlation IDs and a timeout you forgot.&lt;/li&gt;
&lt;li&gt;If the caller can proceed and the work merely needs to &lt;em&gt;eventually&lt;/em&gt; happen →
&lt;strong&gt;asynchronous&lt;/strong&gt;. Sending an email, updating a search index, recalculating a
recommendation, emitting an audit record.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That single question resolves the large majority of cases correctly.&lt;/p&gt;</description></item><item><title>API Contracts and Versioning</title><link>https://architectures.metacog.co.kr/docs/system-design/api-contracts/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/system-design/api-contracts/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You own an API. Someone consumes it. You need to change it. The question is not
&amp;ldquo;how do I version this&amp;rdquo; — it is &amp;ldquo;how do I change this without a synchronised
deploy,&amp;rdquo; and versioning is only one of the answers.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Expand, migrate, contract.&lt;/strong&gt; Never change a contract in place.&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant P as Producer
 participant C as Consumers
 Note over P: 1. EXPAND
 P-&amp;gt;&amp;gt;P: Add new field/endpoint.&amp;lt;br/&amp;gt;Old one still works.
 P-&amp;gt;&amp;gt;C: Deploy. Nothing breaks.
 Note over C: 2. MIGRATE
 C-&amp;gt;&amp;gt;C: Move to the new shape,&amp;lt;br/&amp;gt;at each consumer&amp;#39;s own pace
 C-&amp;gt;&amp;gt;P: Telemetry confirms&amp;lt;br/&amp;gt;old path unused
 Note over P: 3. CONTRACT
 P-&amp;gt;&amp;gt;P: Remove the old field.&amp;lt;br/&amp;gt;Only now.
&lt;/pre&gt;
&lt;p&gt;The third step is the one teams skip, which is why every mature codebase has
deprecated fields from 2019 still in the response. Skipping it is survivable;
skipping steps 1 and 2 is not.&lt;/p&gt;</description></item><item><title>Idempotency and Retries</title><link>https://architectures.metacog.co.kr/docs/system-design/idempotency-and-retries/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/system-design/idempotency-and-retries/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A request times out. The client does not know whether the work happened. It
retries. Now you may have two orders, two charges, or two emails — and the
client still does not know.&lt;/p&gt;
&lt;p&gt;This is not an edge case. In any distributed system, &amp;ldquo;I did not get a response&amp;rdquo;
is indistinguishable from &amp;ldquo;it did not happen,&amp;rdquo; and that ambiguity is permanent.
The only question is whether you designed for it.&lt;/p&gt;</description></item><item><title>Choosing a Datastore Without Regret</title><link>https://architectures.metacog.co.kr/docs/data-and-state/choosing-a-datastore/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/data-and-state/choosing-a-datastore/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;New system, and someone has to pick the database. This is among the most
irreversible decisions available — data outlives code, and every consumer you
did not plan for will be reading it by the time you want to change.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;A relational database, almost certainly Postgres.&lt;/strong&gt; Then make every
alternative argue against it.&lt;/p&gt;
&lt;p&gt;This is not conservatism for its own sake. A modern relational database gives
you, in one system with one operational model: transactions, joins, secondary
indexes, JSON documents with indexing, full-text search, geospatial queries,
range partitioning, logical replication, materialised views, and a
constraint system that catches data corruption before it happens.&lt;/p&gt;</description></item><item><title>Schema Migrations Without Downtime</title><link>https://architectures.metacog.co.kr/docs/data-and-state/zero-downtime-migrations/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/data-and-state/zero-downtime-migrations/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You need to rename a column, split a table, add a constraint, or change a type.
During the deploy, old code and new code both run against the same database.
Whatever you do must be correct for both, simultaneously, in both directions —
because you might roll back.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Expand, migrate, contract&lt;/strong&gt; — the same shape as
&lt;a data-bs-delay="{&amp;#34;hide&amp;#34;:300,&amp;#34;show&amp;#34;:550}" data-bs-html="true" data-bs-title="&lt;a href='https://architectures.metacog.co.kr/docs/system-design/api-contracts/'&gt;&lt;p&gt;SYSTEM DESIGN IN PRACTICE&lt;/p&gt;&lt;strong&gt;API Contracts and Versioning&lt;/strong&gt;&lt;br&gt;A contract lets two teams move at different speeds. Without one, every change is a coordination meeting.&lt;/a&gt;" data-bs-toggle="tooltip" href="https://architectures.metacog.co.kr/docs/system-design/api-contracts/"&gt;API contracts&lt;/a&gt;, applied to storage. Never
change a column in place.&lt;/p&gt;</description></item><item><title>Consistency Models You Actually Need</title><link>https://architectures.metacog.co.kr/docs/data-and-state/consistency-models/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/data-and-state/consistency-models/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Someone says &amp;ldquo;the data must be consistent&amp;rdquo; and everyone nods. Nobody has
defined consistent, and the requirement has quietly been interpreted as &amp;ldquo;every
read everywhere sees every write immediately,&amp;rdquo; which is expensive, sometimes
impossible, and almost never what the business needs.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Strong consistency inside a transactional boundary; eventual consistency
across boundaries.&lt;/strong&gt; Then find the specific invariants that must never be
violated and defend those explicitly.&lt;/p&gt;</description></item><item><title>Caching: The Four Questions</title><link>https://architectures.metacog.co.kr/docs/data-and-state/caching/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/data-and-state/caching/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Something is slow. Someone suggests a cache. It works immediately, everyone is
happy, and six months later you are debugging why one customer sees another
customer&amp;rsquo;s data on Tuesdays.&lt;/p&gt;
&lt;p&gt;Caching is the highest ratio of &amp;ldquo;obvious win&amp;rdquo; to &amp;ldquo;subtle disaster&amp;rdquo; in the
field. The wins are real. So are the disasters.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Before adding any cache, answer these four in writing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;What invalidates it?&lt;/strong&gt; If the answer is &amp;ldquo;a TTL,&amp;rdquo; you have accepted a window
of wrongness. Name the window and confirm someone is okay with it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What is the key, exactly?&lt;/strong&gt; Including tenant, user, locale, permission
context, and API version. Most cache-poisoning incidents are a key missing a
dimension.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What happens when it is empty?&lt;/strong&gt; Cold start, eviction, or a flush. If the
origin cannot survive a 0% hit rate, the cache is not an optimisation — it is
a load-bearing component with no redundancy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What happens when it is wrong?&lt;/strong&gt; Stale price, stale permission, stale
feature flag. Rank the consequence.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Question 3 is the one that causes outages, and question 2 is the one that
causes incidents you have to disclose.&lt;/p&gt;</description></item><item><title>Event Sourcing and CDC: When It Pays</title><link>https://architectures.metacog.co.kr/docs/data-and-state/events-and-cdc/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/data-and-state/events-and-cdc/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Someone proposes &amp;ldquo;event sourcing&amp;rdquo; and the conversation immediately conflates
three separate things: storing state as a log of events, publishing events for
other services to consume, and streaming database changes downstream.&lt;/p&gt;
&lt;p&gt;They have different costs and different payoffs. Separating them is most of the
work.&lt;/p&gt;
&lt;h2 id="the-three-things"&gt;The three things &lt;a href="#the-three-things" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;Event sourcing&lt;/th&gt;
 &lt;th&gt;Event-driven integration&lt;/th&gt;
 &lt;th&gt;Change data capture&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;What it is&lt;/td&gt;
 &lt;td&gt;Your state &lt;strong&gt;is&lt;/strong&gt; the event log; current state is a fold over it&lt;/td&gt;
 &lt;td&gt;Services publish domain events others subscribe to&lt;/td&gt;
 &lt;td&gt;Read the database&amp;rsquo;s replication log, emit row changes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Source of truth&lt;/td&gt;
 &lt;td&gt;The event log&lt;/td&gt;
 &lt;td&gt;Each service&amp;rsquo;s own store&lt;/td&gt;
 &lt;td&gt;The database&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Who defines the schema&lt;/td&gt;
 &lt;td&gt;The domain&lt;/td&gt;
 &lt;td&gt;The publishing team, deliberately&lt;/td&gt;
 &lt;td&gt;The table structure, accidentally&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Main benefit&lt;/td&gt;
 &lt;td&gt;Perfect audit trail, temporal queries, rebuild any projection&lt;/td&gt;
 &lt;td&gt;Decoupling, extensibility&lt;/td&gt;
 &lt;td&gt;Zero application change; get data out of a system you cannot modify&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Main cost&lt;/td&gt;
 &lt;td&gt;Very high. Schema evolution on the log is forever&lt;/td&gt;
 &lt;td&gt;Moderate&lt;/td&gt;
 &lt;td&gt;Couples consumers to your physical schema&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;When it pays&lt;/td&gt;
 &lt;td&gt;Domains where history &lt;em&gt;is&lt;/em&gt; the product: ledgers, trading, compliance&lt;/td&gt;
 &lt;td&gt;Most systems that have grown past two teams&lt;/td&gt;
 &lt;td&gt;Analytics pipelines, migrations, legacy integration&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Use event-driven integration where you have publishers and consumers on
different teams. Use CDC to feed analytics. Do not use event sourcing unless
history is the product.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Trunk-Based Development and Branch Reality</title><link>https://architectures.metacog.co.kr/docs/delivery/trunk-based-development/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/delivery/trunk-based-development/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The branching model argument is usually framed as a workflow preference. It is
not — it is an architecture decision about batch size, and batch size
determines how bad your worst deploy can be.&lt;/p&gt;
&lt;p&gt;A branch that lives for three weeks is three weeks of unintegrated,
unvalidated, unreviewed-in-context change. The merge conflict is the visible
cost. The invisible cost is that nobody knows whether the combined system works
until the moment it all lands.&lt;/p&gt;</description></item><item><title>Pipeline Design: Fast Feedback, Slow Gates</title><link>https://architectures.metacog.co.kr/docs/delivery/pipeline-design/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/delivery/pipeline-design/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The pipeline takes 45 minutes. People stop watching it. They merge and walk
away. Failures are discovered hours later by whoever notices, context is gone,
and the fix is a scramble.&lt;/p&gt;
&lt;p&gt;Pipeline duration is not a convenience issue — it directly sets how large a
batch people are willing to work in, which sets how risky each change is.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Order stages by (probability of catching a failure) ÷ (time to run).&lt;/strong&gt; Cheap,
high-yield checks first; expensive, low-yield checks last.&lt;/p&gt;</description></item><item><title>Progressive Delivery</title><link>https://architectures.metacog.co.kr/docs/delivery/progressive-delivery/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/delivery/progressive-delivery/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A deploy either works or it takes down production for everyone at once. That
binary is a choice, not a law — and it is the choice that makes releases scary,
which makes them rare, which makes them bigger, which makes them scarier.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Separate deploy from release.&lt;/strong&gt; Deploying puts code on servers. Releasing
exposes behaviour to users. Once these are separate events, every release
becomes a dial rather than a switch.&lt;/p&gt;</description></item><item><title>Build Reproducibility and Artifact Promotion</title><link>https://architectures.metacog.co.kr/docs/delivery/build-reproducibility/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/delivery/build-reproducibility/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Production is broken. You want to know what changed. The answer should be a
commit SHA and a diff. Too often it is &amp;ldquo;well, the build pulled &lt;code&gt;latest&lt;/code&gt; on
Tuesday, so it might be a transitive dependency.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Reproducibility is not purity for its own sake. It is the property that makes
debugging, rollback, and incident forensics possible at all.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;One artifact, built once, identified by content, promoted unchanged.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Rollback Is a Feature</title><link>https://architectures.metacog.co.kr/docs/delivery/rollback/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/delivery/rollback/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Something is wrong in production. The fastest path to a working system is
almost always to go back to the last thing that worked. Whether you can do that
in two minutes or two hours was decided weeks earlier, by design choices nobody
labelled as being about rollback.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Every change ships with a known, tested way to undo it — and the undo path is
exercised, not theoretical.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Kubernetes: What You Sign Up For</title><link>https://architectures.metacog.co.kr/docs/platform/kubernetes-reality/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/platform/kubernetes-reality/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The decision is usually framed as &amp;ldquo;should we use Kubernetes?&amp;rdquo; and answered with
either enthusiasm or cynicism. Neither is useful. The honest framing is: &lt;strong&gt;what
problems does it solve, what does it charge, and are you big enough for the
trade to be positive?&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="what-it-actually-gives-you"&gt;What it actually gives you &lt;a href="#what-it-actually-gives-you" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A declarative API for infrastructure.&lt;/strong&gt; You describe desired state; a
control loop reconciles. This is genuinely powerful and is the real product.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A standard vocabulary&lt;/strong&gt; across teams and clouds. Deployment, Service,
Ingress, ConfigMap mean the same thing everywhere.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;An extension point.&lt;/strong&gt; Operators and CRDs let you encode your own
operational knowledge as automation. This is where large organisations get
the most value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bin-packing and self-healing&lt;/strong&gt; for stateless workloads.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-it-charges"&gt;What it charges &lt;a href="#what-it-charges" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Cost&lt;/th&gt;
 &lt;th&gt;Reality&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Conceptual surface&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Pods, Services, Ingress, RBAC, network policy, CNI, CSI, admission control, PDBs, HPAs, taints, affinities. Everyone on the team needs a working model of most of it&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Upgrade treadmill&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Roughly quarterly minor releases with ~14 months of support. API deprecations break manifests. This is permanent work&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Debugging depth&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;A failing request can be application, sidecar, CNI, kube-proxy, DNS, ingress controller, or cloud LB. The failure surface is deep&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;DNS and networking gotchas&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;CoreDNS behaviour, &lt;code&gt;ndots:5&lt;/code&gt;, conntrack limits, and MTU issues will each cost you a day at some point&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Resource management&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Requests and limits are a genuine skill. Set them wrong and you get either OOMKills or a cluster at 20% utilisation costing full price&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Security config&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Default settings are permissive. Pod security, network policy, and RBAC are all opt-in work&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The upgrade treadmill is the one that surprises people. It is not a one-time
adoption cost; it is a recurring tax, forever, and it needs an owner.&lt;/p&gt;</description></item><item><title>Infrastructure as Code That Doesn't Drift</title><link>https://architectures.metacog.co.kr/docs/platform/infrastructure-as-code/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/platform/infrastructure-as-code/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Everything is in Terraform. Then someone fixes an urgent problem in the console
at 2am, and now the code and reality disagree. Six months later a routine
&lt;code&gt;apply&lt;/code&gt; proposes to delete a security group that is holding production
together.&lt;/p&gt;
&lt;p&gt;Drift is not a tooling failure. It is what happens when the code is not the
only way changes get made.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;The declared state is the only state, enforced by a mechanism, not a rule.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Environments, Config, and Secrets</title><link>https://architectures.metacog.co.kr/docs/platform/environments-and-secrets/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/platform/environments-and-secrets/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The app needs a database URL, a feature flag, an API key, and a log level. Some
of these vary per environment, some are sensitive, some change at runtime, and
teams routinely handle all four with the same mechanism — usually environment
variables in a deploy script — and then wonder why rotating a key requires a
redeploy of nine services.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Separate config by &lt;strong&gt;how it changes&lt;/strong&gt; and &lt;strong&gt;who may read it&lt;/strong&gt;:&lt;/p&gt;</description></item><item><title>Multi-Tenancy and Cost Boundaries</title><link>https://architectures.metacog.co.kr/docs/platform/tenancy-and-cost/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/platform/tenancy-and-cost/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You have customers. Their data has to be separated. How separate is a decision
that touches the data model, the deployment topology, the pricing, the
compliance story, and the on-call load — and it is close to impossible to
change later.&lt;/p&gt;
&lt;h2 id="the-three-models"&gt;The three models &lt;a href="#the-three-models" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;pre class="mermaid"&gt;graph TD
 subgraph &amp;#34;Pooled&amp;#34;
 P1[App instance] --&amp;gt; PDB[(One DB,&amp;lt;br/&amp;gt;tenant_id column)]
 end
 subgraph &amp;#34;Bridged&amp;#34;
 B1[App instance] --&amp;gt; BDB1[(Schema A)]
 B1 --&amp;gt; BDB2[(Schema B)]
 end
 subgraph &amp;#34;Siloed&amp;#34;
 S1[App A] --&amp;gt; SDB1[(DB A)]
 S2[App B] --&amp;gt; SDB2[(DB B)]
 end
&lt;/pre&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;Pooled&lt;/th&gt;
 &lt;th&gt;Bridged (schema/DB per tenant)&lt;/th&gt;
 &lt;th&gt;Siloed (stack per tenant)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Cost per tenant&lt;/td&gt;
 &lt;td&gt;Lowest&lt;/td&gt;
 &lt;td&gt;Medium&lt;/td&gt;
 &lt;td&gt;Highest&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Blast radius&lt;/td&gt;
 &lt;td&gt;All tenants&lt;/td&gt;
 &lt;td&gt;All tenants (shared compute)&lt;/td&gt;
 &lt;td&gt;One tenant&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Noisy neighbour&lt;/td&gt;
 &lt;td&gt;Real problem, needs quotas&lt;/td&gt;
 &lt;td&gt;Partially isolated&lt;/td&gt;
 &lt;td&gt;None&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Per-tenant restore&lt;/td&gt;
 &lt;td&gt;Hard&lt;/td&gt;
 &lt;td&gt;Easy&lt;/td&gt;
 &lt;td&gt;Trivial&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Onboarding a tenant&lt;/td&gt;
 &lt;td&gt;Insert a row&lt;/td&gt;
 &lt;td&gt;Run a migration&lt;/td&gt;
 &lt;td&gt;Provision a stack&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Migrating 5000 tenants&lt;/td&gt;
 &lt;td&gt;One migration&lt;/td&gt;
 &lt;td&gt;5000 migrations&lt;/td&gt;
 &lt;td&gt;5000 deploys&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Compliance story&lt;/td&gt;
 &lt;td&gt;&amp;ldquo;We isolate logically&amp;rdquo;&lt;/td&gt;
 &lt;td&gt;Better&lt;/td&gt;
 &lt;td&gt;&amp;ldquo;Your data is physically separate&amp;rdquo;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Deployment complexity&lt;/td&gt;
 &lt;td&gt;Low&lt;/td&gt;
 &lt;td&gt;Medium&lt;/td&gt;
 &lt;td&gt;High, needs real automation&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Pooled&lt;/strong&gt;, with tenant isolation enforced at the lowest layer you can manage.&lt;/p&gt;</description></item><item><title>The Internal Platform as a Product</title><link>https://architectures.metacog.co.kr/docs/platform/platform-as-product/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/platform/platform-as-product/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;An organisation grows past the point where every team can invent its own
deployment, monitoring, and infrastructure approach. Someone forms a platform
team. Six months later there is a platform, a mandate to use it, and a
significant number of teams quietly working around it.&lt;/p&gt;
&lt;p&gt;The failure is almost never technical. It is that the platform was built as
infrastructure rather than as a product with users who have alternatives.&lt;/p&gt;</description></item><item><title>SLOs, Error Budgets, and Saying No</title><link>https://architectures.metacog.co.kr/docs/reliability/slos-and-error-budgets/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/reliability/slos-and-error-budgets/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Leadership wants &amp;ldquo;five nines.&amp;rdquo; Engineering wants time to pay down debt. Product
wants features. Everyone is arguing from intuition, and the loudest voice
wins.&lt;/p&gt;
&lt;p&gt;An SLO converts that argument into arithmetic. That is its real function —
reliability improvement is a side effect.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;One or two SLOs per user-facing service, measured from the user&amp;rsquo;s
perspective, with an error budget that has an agreed consequence.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Observability: What to Actually Wire</title><link>https://architectures.metacog.co.kr/docs/reliability/observability/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/reliability/observability/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You have logs, metrics, and traces, a five-figure monthly bill for them, and
during the last incident nobody could work out why checkout was failing for one
customer segment.&lt;/p&gt;
&lt;p&gt;Volume is not observability. The test is whether you can answer a &lt;em&gt;new&lt;/em&gt;
question about production without shipping code.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Wire these four things, in this order. Each is cheap and each unlocks a class
of question.&lt;/p&gt;</description></item><item><title>Capacity, Load Shedding, and Backpressure</title><link>https://architectures.metacog.co.kr/docs/reliability/capacity-and-backpressure/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/reliability/capacity-and-backpressure/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Traffic doubles. The service slows. Queues grow. Timeouts fire. Clients retry,
which adds load. Latency rises further. Eventually everything times out and the
service is effectively down — and when traffic returns to normal, it &lt;em&gt;stays&lt;/em&gt;
down, because the retry backlog keeps it saturated.&lt;/p&gt;
&lt;p&gt;This is metastable failure. It is the most common way a healthy system dies,
and it is entirely preventable with limits.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Every queue is bounded. Every request has a deadline. Every dependency has a
concurrency limit. Reject early rather than degrade for everyone.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Failure Modes: Timeouts, Breakers, Bulkheads</title><link>https://architectures.metacog.co.kr/docs/reliability/failure-modes/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/reliability/failure-modes/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Every distributed system needs to handle a dependency being slow, failing, or
gone. The patterns are well known. What is less well known is that the standard
configurations are usually wrong, and a misconfigured circuit breaker causes
outages that the unprotected system would not have had.&lt;/p&gt;
&lt;h2 id="timeouts"&gt;Timeouts &lt;a href="#timeouts" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Every network call has a timeout. There are no exceptions.&lt;/strong&gt; A missing timeout
means a thread or connection held indefinitely, and enough of those means
resource exhaustion and a dead service.&lt;/p&gt;</description></item><item><title>Incident Response and Blameless Postmortems</title><link>https://architectures.metacog.co.kr/docs/reliability/incident-response/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/reliability/incident-response/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Something is broken. Several people are in a channel. Someone is running
commands. Someone else is also running commands. Nobody is sure who is talking
to the customer, and the timeline is being reconstructed from memory
afterwards.&lt;/p&gt;
&lt;p&gt;Incident response is a skill and a structure, and teams that have not
practised it improvise badly under stress.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Declare early, assign roles, restore first, investigate second.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Threat Modeling in One Hour</title><link>https://architectures.metacog.co.kr/docs/security/threat-modeling/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/security/threat-modeling/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Threat modelling has a reputation for being a heavyweight process with
specialist tooling that happens once, produces a document, and is never read
again. That reputation is earned, and it is why most teams do not do it.&lt;/p&gt;
&lt;p&gt;The lightweight version takes an hour, catches most of what matters, and can be
repeated whenever the design changes.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Four questions, in order, with the people who actually built the thing:&lt;/p&gt;</description></item><item><title>Identity, Authentication, Authorisation</title><link>https://architectures.metacog.co.kr/docs/security/identity-and-authorization/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/security/identity-and-authorization/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Authentication is a solved problem you should not be solving — use an identity
provider. Authorisation is not solved, is specific to your domain, and is where
the real bugs live: the endpoint that checks you are logged in but not that the
resource is yours.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Authenticate at the edge. Authorise at the resource. Never trust the client
about identity.&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[Client] --&amp;gt;|&amp;#34;credentials&amp;#34;| B[&amp;#34;Identity provider&amp;lt;br/&amp;gt;(OIDC / SAML)&amp;#34;]
 B --&amp;gt;|&amp;#34;token&amp;#34;| A
 A --&amp;gt;|&amp;#34;token&amp;#34;| C[Gateway]
 C --&amp;gt;|&amp;#34;verify signature,&amp;lt;br/&amp;gt;expiry, audience&amp;#34;| C
 C --&amp;gt;|&amp;#34;verified identity&amp;lt;br/&amp;gt;in a trusted header&amp;lt;br/&amp;gt;or re-signed token&amp;#34;| D[Service]
 D --&amp;gt;|&amp;#34;authorise:&amp;lt;br/&amp;gt;may THIS subject do&amp;lt;br/&amp;gt;THIS action on&amp;lt;br/&amp;gt;THIS resource?&amp;#34;| E[(Data)]
 style C fill:#fd6,stroke:#c90,color:#000
 style D fill:#2d7,stroke:#0a5,color:#000
&lt;/pre&gt;
&lt;p&gt;The gateway proves &lt;em&gt;who&lt;/em&gt;. Only the service knows &lt;em&gt;whether&lt;/em&gt; — because
authorisation depends on the resource, and only the service sees the resource.&lt;/p&gt;</description></item><item><title>Secrets and Key Management</title><link>https://architectures.metacog.co.kr/docs/security/secrets-management/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/security/secrets-management/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A database password, an API key for a payment provider, a signing key for
tokens, an SSH key for a legacy box. Each has a different lifetime, blast
radius, and rotation story, and most teams handle all of them with the same
mechanism and the same (never) rotation cadence.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A ladder, best to worst. Move each secret as far up as your platform allows.&lt;/p&gt;</description></item><item><title>Supply Chain: Dependencies, SBOM, Signing</title><link>https://architectures.metacog.co.kr/docs/security/supply-chain/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/security/supply-chain/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A typical application has a handful of direct dependencies and several hundred
transitive ones. Any of them can execute code at install time, at build time,
and at runtime. Your CI has credentials. This is a supply chain, and it is
attacked because it works.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Three layers, in order of value per effort:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Know what you have.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lockfiles committed, exact versions, digest-pinned base images.&lt;/li&gt;
&lt;li&gt;Generate an SBOM at build time and store it with the artifact. When the next
widely-exploited library vulnerability is announced, the question &amp;ldquo;are we
affected, and where&amp;rdquo; should take minutes, not days.&lt;/li&gt;
&lt;li&gt;An inventory of which services use which dependency, queryable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. Reduce what you have.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Least Privilege and Auditability</title><link>https://architectures.metacog.co.kr/docs/security/least-privilege/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/security/least-privilege/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Assume a component is compromised — a leaked credential, a malicious
dependency, a vulnerable endpoint. The question that determines whether this is
an incident or a catastrophe is: &lt;strong&gt;what can it reach?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That answer was determined by permission decisions made long before, usually
under time pressure, usually by granting more than necessary because narrowing
it was fiddly.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Start from zero and add what is needed, with expiry.&lt;/strong&gt; The opposite —
starting broad and narrowing later — never happens, because narrowing risks
breaking something and nobody is rewarded for it.&lt;/p&gt;</description></item><item><title>Architecture Decision Records That Get Read</title><link>https://architectures.metacog.co.kr/docs/knowledge/adr/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/knowledge/adr/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Someone asks &amp;ldquo;why is it built this way?&amp;rdquo; The people who decided have left,
moved teams, or genuinely do not remember. The code shows &lt;em&gt;what&lt;/em&gt; was decided
and nothing about &lt;em&gt;why&lt;/em&gt;, and the reasons — the constraints, the alternatives,
the thing that was true in 2022 and is not true now — are gone.&lt;/p&gt;
&lt;p&gt;An ADR is the cheapest possible fix: one page, written once, at the time.&lt;/p&gt;</description></item><item><title>Diagrams That Age Well</title><link>https://architectures.metacog.co.kr/docs/knowledge/diagrams/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/knowledge/diagrams/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;There is a diagram in the wiki. It has fourteen boxes, no legend, arrows that
might mean data flow or dependency or deployment, and it was last edited two
years ago by someone who has left. Nobody trusts it, everybody references it,
and it is subtly wrong in ways that mislead new joiners for months.&lt;/p&gt;
&lt;h2 id="the-default"&gt;The default &lt;a href="#the-default" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Use the C4 levels&lt;/strong&gt; — not as a formal methodology, but as a rule that each
diagram has exactly one level of abstraction and says which.&lt;/p&gt;</description></item><item><title>Runbooks and On-Call Docs</title><link>https://architectures.metacog.co.kr/docs/knowledge/runbooks/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/knowledge/runbooks/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;3am. An alert fires. The person on call did not write this service, has never
seen this alert, and has about ninety seconds of clear thinking before stress
degrades their judgement.&lt;/p&gt;
&lt;p&gt;The document they open determines how the next hour goes. Most such documents
are written by the person who built the system, for a reader who already
understands it — which is precisely the wrong audience.&lt;/p&gt;</description></item><item><title>Design Reviews and RFCs</title><link>https://architectures.metacog.co.kr/docs/knowledge/design-reviews/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/knowledge/design-reviews/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A design gets built, shipped, and then somebody senior says &amp;ldquo;wait, this
conflicts with what the payments team is doing.&amp;rdquo; That objection existed at
design time. It did not surface because there was no forum, or because the
forum was a meeting where nobody wanted to be the one slowing things down.&lt;/p&gt;
&lt;p&gt;The purpose of a design review is not approval. It is &lt;strong&gt;making disagreement
cheap and early&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>Building a Team Architecture Memory</title><link>https://architectures.metacog.co.kr/docs/knowledge/team-memory/</link><pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate><guid>https://architectures.metacog.co.kr/docs/knowledge/team-memory/</guid><description>&lt;h2 id="the-situation"&gt;The situation &lt;a href="#the-situation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A team has been running a system for four years. The three people who made the
foundational decisions have left. What remains is code, a wiki with a lot of
stale pages, and a set of behaviours nobody can explain — a retry count that is
oddly specific, a service that must be deployed before another, a table nobody
will touch.&lt;/p&gt;
&lt;p&gt;The system still works. Nobody can safely change it. This is the end state of
purely tacit architecture knowledge, and it is extremely common.&lt;/p&gt;</description></item></channel></rss>