<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>Xcoden Resources</title>
  <link>https://xcoden.com/resources/</link>
  <atom:link href="https://xcoden.com/resources/feed.xml" rel="self" type="application/rss+xml"/>
  <description>Notes on e-commerce architecture, platform engineering and custom commerce systems.</description>
  <language>en</language>
  <item>
    <title>Architecture before code</title>
    <link>https://xcoden.com/resources/architecture-before-code/</link>
    <guid isPermaLink="true">https://xcoden.com/resources/architecture-before-code/</guid>
    <pubDate>Mon, 21 Sep 2026 00:00:00 +0000</pubDate>
    <description>The expensive rebuilds we&#x27;ve seen all started as a schema decision nobody wanted to make early. Here is what we settle before the first migration runs, and why.</description>
    <content:encoded><![CDATA[<p>Every custom commerce build we've taken over had the same story. The first version shipped fast. The second version was where the money went. And when you trace the second version back, it almost never comes from a bad feature. It comes from a data model decision made in week one that the whole system then had to work around.</p>
<p>So before we write application code, we settle three things.</p>
<h2 id="the-data-model">The data model</h2>
<p>Not the database schema in the abstract &mdash; the specific questions the business will ask of it. A buyback platform needs to know what an <em>offer</em> is: the price quoted, the condition assumed, the date it expires, and what happens when the device that arrives doesn't match. If those are four columns on an <code>orders</code> table, the first dispute rewrites them into four tables.</p>
<p>The test we use: pick the five reports the owner will ask for in month three, and write the query for each one against the proposed model. If a query needs a heuristic ("status was probably X at the time"), the model is missing a fact, and it's cheaper to add it now than to backfill it.</p>
<h2 id="the-service-boundaries">The service boundaries</h2>
<p>A commerce system has a handful of things that genuinely operate on their own clock: pricing, inventory, fulfillment, payments. They don't need to be separate services on day one. They do need to be separate <strong>modules</strong> with a defined interface, so that when the pricing engine needs to change every week and the payout pipeline needs to change never, they aren't tangled in the same controller.</p>
<p>The boundary we draw most often is between <em>what the customer sees</em> and <em>what the operation runs on</em>. Storefront code changes with marketing. Operational logic changes with the business. Coupling them means every promotion is a deployment risk.</p>
<h2 id="what-stays-off-the-shelf">What stays off the shelf</h2>
<p>Building from scratch is not the goal. The goal is to build the layer the business actually runs on and buy everything else. Payments, email, search, the storefront theme &mdash; these are solved problems, and a custom version is a liability, not an asset.</p>
<p>The layer a platform <em>won't</em> do is usually the layer the business depends on. That's the layer we build. Deciding which layer that is, before any code exists, is most of the architecture work.</p>
<hr>
<p>None of this takes long. A week of conversation and a document that fits on a few pages. The point is that it happens before the first migration, because after that, every decision has a cost attached.</p>]]></content:encoded>
  </item>
</channel>
</rss>
