<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Sazinga — Insights</title>
    <link>https://sazinga.com/insights/</link>
    <atom:link href="https://sazinga.com/rss.xml" rel="self" type="application/rss+xml" />
    <atom:link href="https://pubsubhubbub.appspot.com/" rel="hub" />
    <description>Writing from the Sazinga engineering team on building and running operational software.</description>
    <language>en-GB</language>
    <lastBuildDate>Fri, 11 Sep 2026 00:00:00 GMT</lastBuildDate>
    <item>
      <title>A redirect that returns 404 teaches a search engine nothing</title>
      <link>https://sazinga.com/insights/a-redirect-that-404s-teaches-nothing/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-redirect-that-404s-teaches-nothing/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>We mapped 140 legacy URLs and still served stale copy for days: engines held them without a trailing slash, and nginx only adds one for a real directory.</description>
      <category>search</category>
    </item>
    <item>
      <title>A content schema is a publishing gate a CMS cannot give you</title>
      <link>https://sazinga.com/insights/a-schema-that-refuses-to-publish/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-schema-that-refuses-to-publish/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>Typed frontmatter means a page with a missing meta description fails the build instead of shipping. We hit it four characters over a limit this week.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>We rebuilt our own site as static HTML, and the attack surface went with it</title>
      <link>https://sazinga.com/insights/a-site-with-nothing-to-reinfect/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-site-with-nothing-to-reinfect/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>Moving from WordPress to a static build removed the database, the plugin surface, the admin login and the file writes — not by hardening them, by not having them.</description>
      <category>security</category>
    </item>
    <item>
      <title>A website is not a web application, and app teams keep shipping one as the other</title>
      <link>https://sazinga.com/insights/a-website-is-not-a-web-application/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-website-is-not-a-web-application/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>Different client, different contract, different failure modes — when the consumer of your output is a machine that never logs in and leaves after one request.</description>
      <category>search</category>
    </item>
    <item>
      <title>Anyone could set their own sales target, and half the screen did nothing</title>
      <link>https://sazinga.com/insights/anyone-could-set-their-own-sales-target/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/anyone-could-set-their-own-sales-target/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>The complaint was that the target screen was unfriendly. Underneath it, the save endpoint checked nothing and 866 of 877 targets were in the wrong units.</description>
      <category>security</category>
    </item>
    <item>
      <title>Every page we built said noindex, and nothing complained</title>
      <link>https://sazinga.com/insights/every-page-we-built-said-noindex/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/every-page-we-built-said-noindex/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>A build flag derived from the hostname put noindex on all 245 pages. Deploying one of those would have removed the whole site from search, silently.</description>
      <category>search</category>
    </item>
    <item>
      <title>Never ask the AI to enforce permissions</title>
      <link>https://sazinga.com/insights/never-ask-the-ai-to-enforce-permissions/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/never-ask-the-ai-to-enforce-permissions/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>A prompt saying &quot;only show their region&quot; is an argument with a text predictor. The database has to be what refuses — and one view clause silently undoes it.</description>
      <category>security</category>
    </item>
    <item>
      <title>Nine thousand contacts nobody could call, and one import that kept making more</title>
      <link>https://sazinga.com/insights/nine-thousand-contacts-nobody-could-call/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/nine-thousand-contacts-nobody-could-call/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>The owner suspected the phone numbers were wrong. They were — 9,300 of them — and the check meant to prevent it had only ever tested one end.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>One answer engine quoted us; the other could not say what we do</title>
      <link>https://sazinga.com/insights/one-engine-quoted-us-the-other-could-not/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/one-engine-quoted-us-the-other-could-not/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>Same site, same day, same crawl access. Perplexity cited the product accurately. ChatGPT described the company we had stopped being. The gap was specificity.</description>
      <category>search</category>
    </item>
    <item>
      <title>The field team said the app was broken. The app was fine.</title>
      <link>https://sazinga.com/insights/the-field-team-said-the-app-was-broken/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-field-team-said-the-app-was-broken/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>Reps could not start their day and attendance data was unusable. Nothing was down — a Google API sat inside the one request that had to succeed.</description>
      <category>operations</category>
    </item>
    <item>
      <title>The model should never produce the number, and the cheap model still lost</title>
      <link>https://sazinga.com/insights/the-model-should-never-produce-the-number/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-model-should-never-produce-the-number/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>An owner asked what it would cost to let their sales team question their own data. We measured it, our cheap-model theory lost, and the answer was still yes.</description>
      <category>ai</category>
    </item>
    <item>
      <title>The rebuild did not fix the lead problem, and was never going to</title>
      <link>https://sazinga.com/insights/the-rebuild-did-not-fix-the-lead-problem/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-rebuild-did-not-fix-the-lead-problem/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>92% of all form submissions were job applications and 87% of search clicks were the company name. A framework change does not create commercial demand.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Twenty-one of the joins were invisible to the schema, so we extracted them from the code</title>
      <link>https://sazinga.com/insights/twenty-one-joins-the-schema-does-not-know-about/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/twenty-one-joins-the-schema-does-not-know-about/</guid>
      <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
      <description>Text-to-SQL guesses join paths. We catalogued the real ones from the queries the service runs, graded by evidence, and checked every table name against the database.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>From the quotation to the cutting list, without rebuilding the job</title>
      <link>https://sazinga.com/insights/from-the-quotation-to-the-cutting-list/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/from-the-quotation-to-the-cutting-list/</guid>
      <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
      <description>Your quotation already knows what the job consumes. Turning that into a bill of materials and a nested cutting list without rebuilding it by hand.</description>
      <category>operations</category>
    </item>
    <item>
      <title>GST on a fabrication quotation — what goes in the taxable amount</title>
      <link>https://sazinga.com/insights/gst-on-a-fabrication-quotation/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/gst-on-a-fabrication-quotation/</guid>
      <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
      <description>Where transport and installation sit relative to GST on a fabrication quotation, CGST and SGST versus IGST, and the ordering that changes the total.</description>
      <category>operations</category>
    </item>
    <item>
      <title>How to price a stainless steel work table</title>
      <link>https://sazinga.com/insights/how-to-price-a-stainless-steel-work-table/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/how-to-price-a-stainless-steel-work-table/</guid>
      <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
      <description>Cost a six-foot stainless work table step by step — sheet weight, tube, hardware, labour and margin — with every figure shown so you can check it against yours.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Margin on selling versus markup on cost — the ₹900 a table nobody notices</title>
      <link>https://sazinga.com/insights/margin-on-selling-versus-markup-on-cost/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/margin-on-selling-versus-markup-on-cost/</guid>
      <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
      <description>Margin on selling and markup on cost are not the same twenty per cent. The arithmetic, the conversion table, and what the confusion costs over a year.</description>
      <category>operations</category>
    </item>
    <item>
      <title>SS 202, 304 and 316 — what actually changes in your quotation</title>
      <link>https://sazinga.com/insights/ss-202-vs-304-vs-316-in-your-quotation/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/ss-202-vs-304-vs-316-in-your-quotation/</guid>
      <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
      <description>SS 202 against 304 against 316 for fabricators — what differs in the metal, where each grade belongs, and the price spread on one identical table.</description>
      <category>operations</category>
    </item>
    <item>
      <title>What quotation software for fabricators actually needs to do</title>
      <link>https://sazinga.com/insights/what-fabrication-quoting-software-needs-to-do/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/what-fabrication-quoting-software-needs-to-do/</guid>
      <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
      <description>Quoting software for manufacturers mostly assumes a catalogue. Made-to-order work needs something else, and here are six tests to run on any vendor demo.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Why your quoting spreadsheet eventually lies to you</title>
      <link>https://sazinga.com/insights/why-your-quoting-spreadsheet-eventually-lies/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/why-your-quoting-spreadsheet-eventually-lies/</guid>
      <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
      <description>Estimating spreadsheets fail in predictable ways — copied files, stale rates, hidden assumptions. Where quoting in Excel breaks, and what fixes it.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Hoarding, unipole, gantry: OOH formats and sizes in India</title>
      <link>https://sazinga.com/insights/hoarding-sizes-and-ooh-formats-in-india/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/hoarding-sizes-and-ooh-formats-in-india/</guid>
      <pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate>
      <description>What a hoarding, unipole, gantry and pole kiosk actually are, the sizes each is commonly built at, and why there is no single standard size.</description>
      <category>operations</category>
    </item>
    <item>
      <title>How to start an outdoor advertising business in India</title>
      <link>https://sazinga.com/insights/how-to-start-an-outdoor-advertising-business-in-india/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/how-to-start-an-outdoor-advertising-business-in-india/</guid>
      <pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate>
      <description>The two kinds of outdoor advertising business, what each needs to start, the permissions involved, and the three numbers that decide if it works.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Card rate, net rate and commission: how OOH pricing really works</title>
      <link>https://sazinga.com/insights/rate-card-net-rate-and-agency-commission/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/rate-card-net-rate-and-agency-commission/</guid>
      <pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate>
      <description>Card rate versus net rate, how agency commission is applied, what printing and mounting really cost, and how to quote so procurement cannot argue.</description>
      <category>operations</category>
    </item>
    <item>
      <title>What billboard management software actually needs to do</title>
      <link>https://sazinga.com/insights/what-billboard-management-software-needs-to-do/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/what-billboard-management-software-needs-to-do/</guid>
      <pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate>
      <description>Why most billboard software solves the wrong problem, the eight things an out-of-home system must do, and the questions to ask before you buy.</description>
      <category>operations</category>
    </item>
    <item>
      <title>How many days did your sites sit empty last month?</title>
      <link>https://sazinga.com/insights/how-many-days-did-your-sites-sit-empty/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/how-many-days-did-your-sites-sit-empty/</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>Vacancy is the biggest cost in an out-of-home business and the one nobody counts. How to work out what your empty hoarding days actually cost.</description>
      <category>operations</category>
    </item>
    <item>
      <title>One hoarding, two clients, the same month</title>
      <link>https://sazinga.com/insights/one-hoarding-two-clients-same-month/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/one-hoarding-two-clients-same-month/</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>Double-booking an advertising face is almost never carelessness — it is a hold nobody confirmed. How it happens, and how to make it impossible.</description>
      <category>operations</category>
    </item>
    <item>
      <title>&quot;Send the photo&quot; — and the hunt that follows</title>
      <link>https://sazinga.com/insights/send-the-photo-proof-of-display/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/send-the-photo-proof-of-display/</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>The proof-of-display photograph usually exists; finding it is the problem. What a client is really asking for, and how to answer in thirty seconds.</description>
      <category>operations</category>
    </item>
    <item>
      <title>The proposal that took ten minutes</title>
      <link>https://sazinga.com/insights/the-proposal-that-took-ten-minutes/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-proposal-that-took-ten-minutes/</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>Out-of-home work is lost on turnaround and completeness, not on rate. What belongs in a proposal, and how to stop it taking a whole evening.</description>
      <category>operations</category>
    </item>
    <item>
      <title>What billboard advertising actually costs in India</title>
      <link>https://sazinga.com/insights/what-billboard-advertising-costs-in-india/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/what-billboard-advertising-costs-in-india/</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>What hoardings, unipoles and gantries fetch across Indian markets, the five things that set the rate, and how to price your own inventory.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Why out-of-home payments get stuck, and what actually unsticks them</title>
      <link>https://sazinga.com/insights/why-outdoor-media-payments-get-stuck/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/why-outdoor-media-payments-get-stuck/</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>Payments freeze because the invoice and the purchase order describe different things. Where that mismatch comes from, and how to remove it.</description>
      <category>operations</category>
    </item>
    <item>
      <title>The 3D preview is generated from the same inputs that produced the price, and stored nowhere</title>
      <link>https://sazinga.com/insights/a-3d-preview-generated-from-the-price/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-3d-preview-generated-from-the-price/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Dimensions and features already sit on a quote line. Turning them into geometry needs an archetype layout and a registry keyed by code, not a modelling pipeline.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>A column named id is a naming convention, not a type</title>
      <link>https://sazinga.com/insights/a-column-named-id/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-column-named-id/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Converting forty key columns to a single id format, three of them had to be reverted, because what they held was a handle, a display name and a mixed bag.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>A hundred hardcoded defaults, and the cause was a permission a field rep does not have</title>
      <link>https://sazinga.com/insights/a-default-behind-an-admin-permission/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-default-behind-an-admin-permission/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The clients hardcoded language, timezone and currency everywhere. The only endpoint holding the real values needed a permission a sales rep never gets.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>A draft invoice must not have a number, and a sequence cannot give you a gapless one</title>
      <link>https://sazinga.com/insights/a-draft-invoice-must-not-have-a-number/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-draft-invoice-must-not-have-a-number/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Auditors ask why invoice 41 is missing. A database sequence will make holes, and a number allocated at draft becomes a hole the moment the draft is discarded.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>A filter your API ignores is worse than a filter that returns an error</title>
      <link>https://sazinga.com/insights/a-filter-your-api-ignores/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-filter-your-api-ignores/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Two endpoints silently discarded the customer filter and returned every customer&apos;s pricing. The framework was doing what it documents, on every route, forever.</description>
      <category>security</category>
    </item>
    <item>
      <title>A missing translation key is not an error anywhere, which is why users see them</title>
      <link>https://sazinga.com/insights/a-missing-translation-key-is-not-an-error/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-missing-translation-key-is-not-an-error/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Forty-seven error codes the API could emit had no copy in the portal, so users read raw key strings. Nothing in the stack treats that as a failure.</description>
      <category>product</category>
    </item>
    <item>
      <title>A permission called &quot;read your own certificates&quot; does not know whose certificates you are reading</title>
      <link>https://sazinga.com/insights/a-permission-is-not-a-scope/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-permission-is-not-a-scope/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The gate proves you may perform a kind of action. It says nothing about which rows, and in eight handlers the row restriction was eight copied lines.</description>
      <category>security</category>
    </item>
    <item>
      <title>The public quote link reuses the exporter, so it cannot leak anything the PDF would not</title>
      <link>https://sazinga.com/insights/a-public-link-that-cannot-leak-more-than-the-pdf/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-public-link-that-cannot-leak-more-than-the-pdf/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A no-login share link is a new way for internal costs to escape. Building it on the redaction the exporter already does removes a whole class of mistake.</description>
      <category>security</category>
    </item>
    <item>
      <title>A compliance register is not a list of obligations, it is a rule that produces a list</title>
      <link>https://sazinga.com/insights/a-register-is-a-rule-that-produces-a-list/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-register-is-a-rule-that-produces-a-list/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The first model was a person, a certificate and an expiry date. Then came a register of 184 obligations across 15 domains, almost none of them certificates.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>The repository had a script to fill in the numbers the product was meant to compute</title>
      <link>https://sazinga.com/insights/a-script-to-fill-in-the-missing-job/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-script-to-fill-in-the-missing-job/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A backfill and a validator, both carefully written, both compensating for an aggregation job that was specified in a schema comment and never built.</description>
      <category>operations</category>
    </item>
    <item>
      <title>A shared test tenant is global mutable state, and it fails like global mutable state</title>
      <link>https://sazinga.com/insights/a-shared-test-tenant-is-global-mutable-state/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-shared-test-tenant-is-global-mutable-state/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Two suites invited members and never removed them. Nineteen accumulated, the seat limit tripped, and unrelated suites started failing on a rule they never touched.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>The status column said active, and nothing had looked at it since the day it was written</title>
      <link>https://sazinga.com/insights/a-status-nobody-updates/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-status-nobody-updates/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A credential row carried both an expiry date and a status label. Only the date changes meaning as time passes, so every query had to distrust the label.</description>
      <category>product</category>
    </item>
    <item>
      <title>A view runs as its owner, which is how row-level security gets bypassed by a report</title>
      <link>https://sazinga.com/insights/a-view-runs-as-its-owner/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-view-runs-as-its-owner/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Row-level security on the base tables does not protect a view over them. The default is owner privileges, and an aggregate leak looks like a slightly high number.</description>
      <category>security</category>
    </item>
    <item>
      <title>An in-app assistant that cannot call out, because the index is the customer&apos;s entire pricing model</title>
      <link>https://sazinga.com/insights/an-assistant-that-never-leaves-the-box/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/an-assistant-that-never-leaves-the-box/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Designing a retrieval assistant to run on the same host as the application, on two shared cores with no accelerator, and to fail closed rather than fall back.</description>
      <category>ai</category>
    </item>
    <item>
      <title>An endpoint nobody can reach is not a feature, and a search box that does not search is worse</title>
      <link>https://sazinga.com/insights/an-endpoint-nobody-can-reach-is-not-a-feature/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/an-endpoint-nobody-can-reach-is-not-a-feature/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A field-force product where a rep could not take an order on the phone. The API was complete, the module was marked done, and the flow did not exist on any client.</description>
      <category>product</category>
    </item>
    <item>
      <title>The import produced 2,698 rows where I expected 2,800, and the difference was the whole point</title>
      <link>https://sazinga.com/insights/an-import-is-not-done-when-it-runs/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/an-import-is-not-done-when-it-runs/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A clean import run proves nothing. Reconciling every entity count against the source, and naming the cause of every difference, is what proves it.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>An invoice that is not real until a third party says so</title>
      <link>https://sazinga.com/insights/an-invoice-that-is-not-real-yet/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/an-invoice-that-is-not-real-yet/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Statutory real-time invoicing turns each sale into a distributed transaction with a regulator. The first design put the network call inside the sale transaction.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Append-only is a database privilege, not a coding convention</title>
      <link>https://sazinga.com/insights/append-only-is-a-privilege-not-a-convention/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/append-only-is-a-privilege-not-a-convention/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A draft function set a row&apos;s identifier after inserting it. The table had UPDATE revoked, so the schema would have rejected code that every review had passed.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Bulk import is a second front door to every write endpoint you have</title>
      <link>https://sazinga.com/insights/bulk-import-is-a-second-front-door/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/bulk-import-is-a-second-front-door/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>One permission to import, and the target resource named in the request body. That combination lets a role create records it has no permission to create.</description>
      <category>security</category>
    </item>
    <item>
      <title>Adding millimetres to an inch-based pricing engine without touching a single stored number</title>
      <link>https://sazinga.com/insights/convert-units-at-the-boundary/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/convert-units-at-the-boundary/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Every pricing rule assumed inches. The customer wanted to enter millimetres. Converting at the API boundary was the only change that could not corrupt old quotes.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>Development mode and release mode are different programs</title>
      <link>https://sazinga.com/insights/development-mode-and-release-mode-are-different-programs/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/development-mode-and-release-mode-are-different-programs/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The first release build of the mobile app failed on two configuration bugs weeks old. Development mode had never touched either code path.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>Every question was correct and the whole set was broken</title>
      <link>https://sazinga.com/insights/every-answer-was-option-one/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/every-answer-was-option-one/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A hundred and fifty multiple-choice questions all had the answer in the first position. Each one was right. The distribution was the defect.</description>
      <category>product</category>
    </item>
    <item>
      <title>A pricing language with two keywords, because the third one would have been a mistake</title>
      <link>https://sazinga.com/insights/formulas-that-call-formulas/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/formulas-that-call-formulas/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Thirteen of 362 pricing rules needed to call other rules and branch on a dimension. Keeping the language to CALL and CASE is what kept it safe.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>Two rows in the prospect list were the same business, and every useful column was generated</title>
      <link>https://sazinga.com/insights/generated-columns-are-hypotheses/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/generated-columns-are-hypotheses/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A scraped and model-enriched dataset looks like research. Separating observed fields from generated ones stops you building for a customer who does not exist.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Half a delimiter is a perfectly normal thing to receive</title>
      <link>https://sazinga.com/insights/half-a-delimiter/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/half-a-delimiter/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A marker protocol let one reply carry both chat and a draft. Truncation delivered the opening marker without the closing one, and the raw marker reached the screen.</description>
      <category>ai</category>
    </item>
    <item>
      <title>I reported a build as passing, and it was the exit code of the command I piped it into</title>
      <link>https://sazinga.com/insights/i-reported-the-exit-code-of-the-wrong-command/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/i-reported-the-exit-code-of-the-wrong-command/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The build output was long, so it went through a pager. The pipeline reported the pager&apos;s exit status. The build had failed and the report said it succeeded.</description>
      <category>operations</category>
    </item>
    <item>
      <title>The document number was six digits of a clock, and the retry loop was the giveaway</title>
      <link>https://sazinga.com/insights/invoice-number-from-a-clock/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/invoice-number-from-a-clock/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A comment said the numbering scheme avoided race conditions. The loop underneath it retried on duplicate key ten times, which is what you write when it does not.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>The local database was production, and a typo of mine is the only reason it survived</title>
      <link>https://sazinga.com/insights/localhost-was-production/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/localhost-was-production/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A tunnel makes a remote database answer on localhost. That is what it is for, and it is why every migration run that afternoon went to the live system.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Logging out cleared a variable in the browser, and the token stayed valid for eight more hours</title>
      <link>https://sazinga.com/insights/logout-that-only-the-browser-heard/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/logout-that-only-the-browser-heard/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>There was a sessions table with a revocation column and a token hash. Nothing ever wrote a row to it, and nothing ever read one.</description>
      <category>security</category>
    </item>
    <item>
      <title>Fifty-seven screens do not divide into seven workers without a foundation</title>
      <link>https://sazinga.com/insights/make-the-seam-mechanical/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/make-the-seam-mechanical/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Every contract bug in the project so far had been between contributors rather than inside one, so the rebuild started by making the seams mechanical.</description>
      <category>product</category>
    </item>
    <item>
      <title>Not set and zero are different answers, and one input box cannot hold both</title>
      <link>https://sazinga.com/insights/not-set-and-zero-are-different-answers/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/not-set-and-zero-are-different-answers/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A reorder level of zero means alert me when it runs out. No reorder level means never alert me. The empty string coerces to zero and the distinction is gone.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>The notifications were correct, and every one of them went to nobody</title>
      <link>https://sazinga.com/insights/notifications-to-nobody/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/notifications-to-nobody/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Nine send points, each carefully guarded, firing into an empty token table because the app had never called either registration endpoint.</description>
      <category>product</category>
    </item>
    <item>
      <title>The software was multi-tenant on day one and onboarding a second tenant was still a project</title>
      <link>https://sazinga.com/insights/onboarding-that-needs-a-developer/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/onboarding-that-needs-a-developer/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Tenant isolation is the easy half. If loading a customer&apos;s pricing rules needs a developer, your customer ceiling is your developer capacity.</description>
      <category>operations</category>
    </item>
    <item>
      <title>The same end-to-end suite runs before the push and after the deploy, pointed at a different host</title>
      <link>https://sazinga.com/insights/one-test-suite-pointed-at-any-deployment/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/one-test-suite-pointed-at-any-deployment/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Pre-push tests and post-deploy checks are usually two suites that drift apart. Parameterising one suite by base URL removes the drift and the second suite.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Only a server that answered should spend a retry</title>
      <link>https://sazinga.com/insights/only-a-server-that-answered-spends-a-retry/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/only-a-server-that-answered-spends-a-retry/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A phone out of coverage for a day burned its retry budget on failed connections and parked a valid order as rejected. That is the loss a queue prevents.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>Price the feature, not the product, or your catalogue grows faster than you can maintain it</title>
      <link>https://sazinga.com/insights/price-the-feature-not-the-product/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/price-the-feature-not-the-product/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>One made-to-order product had 24 features and 62 variants. Pricing at product level is combinatorially hopeless; pricing per feature is not.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>The pricing spreadsheet had twelve formulas that were referenced but never written</title>
      <link>https://sazinga.com/insights/pricing-that-lives-in-a-spreadsheet/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/pricing-that-lives-in-a-spreadsheet/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>What auditing a fabricator&apos;s quoting workbook revealed about how bespoke pricing really works, and which parts of it a person was silently holding together.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>Three of the customer&apos;s own quotations told me more than the requirements call did</title>
      <link>https://sazinga.com/insights/read-three-real-documents-before-designing-the-output/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/read-three-real-documents-before-designing-the-output/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The output document is a specification. Reading real ones confirmed eight pending requests, produced several more, and settled two arguments about tax.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>Redacting the payload and not the diff means you redacted nothing</title>
      <link>https://sazinga.com/insights/redacting-the-payload-but-not-the-diff/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/redacting-the-payload-but-not-the-diff/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The audit trail masked the request body and stored the before-and-after values in clear. Then the viewer rendered two masked values as &quot;nothing changed&quot;.</description>
      <category>security</category>
    </item>
    <item>
      <title>Remove and Add are not inverses, so the child came back as a stranger</title>
      <link>https://sazinga.com/insights/remove-and-add-are-not-inverses/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/remove-and-add-are-not-inverses/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Removing a child archived the row. Adding her back created a new one. Her whole history stayed behind, and her old tablet credential stayed live.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Run every pricing formula twice, once on cost and once on selling, and never mix the results</title>
      <link>https://sazinga.com/insights/run-the-formulas-twice/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/run-the-formulas-twice/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Knowing what to charge is not knowing whether the job is worth taking. Two evaluations through the same rules give per-feature margin without a second engine.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>A site is not a type, it is a set of capabilities, and the difference shows up in month two</title>
      <link>https://sazinga.com/insights/sites-are-capabilities-not-types/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/sites-are-capabilities-not-types/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>One building held a press, a store and a shop. A type column forces a choice; a capability set does not, and the check reading it used the wrong operator.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Six quizzes created 0.6 seconds apart, and the child was served the wrong one</title>
      <link>https://sazinga.com/insights/six-rows-and-no-order-by/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/six-rows-and-no-order-by/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A stale closure in a loop created six rows where one was intended, and an unordered query picked whichever of them the database felt like returning.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>Soft delete needs a taxonomy of children, not a decision per table</title>
      <link>https://sazinga.com/insights/soft-delete-needs-a-taxonomy-of-children/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/soft-delete-needs-a-taxonomy-of-children/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Deleting a product left 211 orphaned price entries and 104 orphaned variants. Fixing the product path missed the variant path, which orphaned exactly the same rows.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Store the working, not just the answer, and features you have not thought of become cheap</title>
      <link>https://sazinga.com/insights/store-the-working-not-just-the-answer/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/store-the-working-not-just-the-answer/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Keeping the full evaluation trace on the quote line paid for itself twice — in explaining old quotes, and in a bill of materials nobody had planned for.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>The backlog said it was not built, and it had shipped weeks earlier</title>
      <link>https://sazinga.com/insights/the-backlog-said-it-was-not-built/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-backlog-said-it-was-not-built/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A gap register sent two people to rebuild an offline layer that already existed. It was wrong six times, and each entry was wrong in the same specific way.</description>
      <category>operations</category>
    </item>
    <item>
      <title>A check constraint made over-delivery impossible to record, and lorries do not read constraints</title>
      <link>https://sazinga.com/insights/the-check-that-forbade-over-delivery/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-check-that-forbade-over-delivery/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The received quantity could not exceed the ordered quantity. That is a policy, not a fact, and the warehouse hit it the first time a supplier sent a full pallet.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>The capability check ran for employees and skipped the owner, who chose the site himself</title>
      <link>https://sazinga.com/insights/the-check-that-skipped-the-owner/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-check-that-skipped-the-owner/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A middleware validated that a site could take till transactions. It returned early for account owners, and owners were the only ones who could name the site.</description>
      <category>security</category>
    </item>
    <item>
      <title>The dashboard guessed whether the number was a percentage, and turned 1% into 100%</title>
      <link>https://sazinga.com/insights/the-dashboard-guessed-the-unit/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-dashboard-guessed-the-unit/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A helper decided a stored value was a fraction if it was between zero and one. The one organisation that most needed the alarm got a perfect score instead.</description>
      <category>product</category>
    </item>
    <item>
      <title>A credential expiring today was in neither the expiring list nor the expired list</title>
      <link>https://sazinga.com/insights/the-day-that-fell-between-two-filters/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-day-that-fell-between-two-filters/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Four places asked &quot;is this about to run out&quot; and four expressions answered. Two excluded today, one included it, and one forgot to exclude revoked records.</description>
      <category>product</category>
    </item>
    <item>
      <title>The deploy printed a warning, then printed Done, and the old code kept serving</title>
      <link>https://sazinga.com/insights/the-deploy-said-done/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-deploy-said-done/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A restart step that could not get the privilege it needed logged a warning and carried on. Every deploy reported success while changing nothing.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Fourteen fabrication drawings, every one stamped not to scale, and what they could still prove</title>
      <link>https://sazinga.com/insights/the-drawings-were-not-the-specification/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-drawings-were-not-the-specification/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The CAD files looked like the authoritative source for dimensions and geometry. They were neither. What they were useful for was checking the formulas.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>The uniqueness rule was doing concurrency work and nobody had noticed</title>
      <link>https://sazinga.com/insights/the-guard-that-was-doing-concurrency-work/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-guard-that-was-doing-concurrency-work/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>One dispatch per order was a scope decision. Removing it for partial shipments exposed a race where two dispatches could each ship the last unit.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>The model worked with my key and with nobody else&apos;s</title>
      <link>https://sazinga.com/insights/the-model-list-is-a-catalogue/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-model-list-is-a-catalogue/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A pinned model returned 404 for every newly created key while still appearing in the provider&apos;s own model list. Availability is a per-account fact.</description>
      <category>ai</category>
    </item>
    <item>
      <title>The model gets a verdict field and the person gets a signature field, and they never merge</title>
      <link>https://sazinga.com/insights/the-model-triages-the-person-signs/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-model-triages-the-person-signs/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Reviewing 362 business-authored pricing rules needed an ordering, not an oracle. Keeping the AI verdict in its own column is what made it safe to use.</description>
      <category>ai</category>
    </item>
    <item>
      <title>The quiz score was a fine proxy for reading, except on the lessons that mattered</title>
      <link>https://sazinga.com/insights/the-proxy-fails-where-it-matters/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-proxy-fails-where-it-matters/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A proxy metric that works on average can fail completely on one part of its domain, and the part it fails on is often the part you added it for.</description>
      <category>product</category>
    </item>
    <item>
      <title>The readiness screen reported 1,081 missing pricing rules. About 33 of them were real</title>
      <link>https://sazinga.com/insights/the-readiness-screen-that-counted-wrong/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-readiness-screen-that-counted-wrong/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A completeness dashboard counted every variant of every feature as required. The import was fine; the counting rule was wrong, and it hid the real gaps.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>The tables existed, the columns existed, and not one route served them</title>
      <link>https://sazinga.com/insights/the-tables-existed-and-no-route-did/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-tables-existed-and-no-route-did/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Seventy-five endpoints, all parent-facing. The child&apos;s half of the product had a schema, a plan and a design, and no server to talk to.</description>
      <category>product</category>
    </item>
    <item>
      <title>An enforcement rule with no operator surface is an outage waiting for a date</title>
      <link>https://sazinga.com/insights/the-trial-gate-with-no-operator-surface/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-trial-gate-with-no-operator-surface/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Twenty-five of thirty-five test suites went red with no code change. The shared tenant&apos;s trial had expired four days earlier and nothing had said so.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Three code paths decremented the same stock column, and only one of them took a lock</title>
      <link>https://sazinga.com/insights/three-paths-one-stock-column/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/three-paths-one-stock-column/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A sale, a production run and an adjustment all wrote the same inventory row. One took a row lock, one wrote a ledger entry, and one did neither.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>TRUNCATE CASCADE does not delete related rows, it empties related tables</title>
      <link>https://sazinga.com/insights/truncate-cascade-empties-tables/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/truncate-cascade-empties-tables/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Resetting the tenant data wiped every system role and every permission grant, because one nullable column made the roles table a child of the organisations table.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Twelve of fifteen questions, and a sentence saying which three are missing</title>
      <link>https://sazinga.com/insights/twelve-of-fifteen/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/twelve-of-fifteen/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Ask a model for fifteen items and you may get twelve. The choice is between failing, quietly shortening the list, or returning the twelve and saying so.</description>
      <category>ai</category>
    </item>
    <item>
      <title>The lesson needed two facts to be true, and the screen only asked for one</title>
      <link>https://sazinga.com/insights/two-facts-one-screen/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/two-facts-one-screen/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Publish was a button. Assign was an item in an overflow menu on another screen. The child&apos;s tablet needed both, and said nothing when it had one.</description>
      <category>product</category>
    </item>
    <item>
      <title>A material grade sometimes changes the rate and sometimes changes the whole calculation</title>
      <link>https://sazinga.com/insights/two-ways-a-grade-changes-a-price/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/two-ways-a-grade-changes-a-price/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The source workbook had two formula columns per row, one per grade. That single detail decides how a bespoke pricing engine has to resolve rules.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>An action belongs in an offline queue only if a replay can be proved either way</title>
      <link>https://sazinga.com/insights/what-belongs-in-an-offline-queue/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/what-belongs-in-an-offline-queue/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Offline delivery capture was a fiction, because the screen that records it could not be opened without a connection. The queue worked. Nothing could reach it.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>The constraint names remembered a table that no longer existed</title>
      <link>https://sazinga.com/insights/what-constraint-names-remember/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/what-constraint-names-remember/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>A production output table had a nullable parent column, an old parent beside it, and two identical foreign keys — one migration, told three ways.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Your sync cursor cannot be a timestamp, because timestamps are not unique</title>
      <link>https://sazinga.com/insights/your-sync-cursor-cannot-be-a-timestamp/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/your-sync-cursor-cannot-be-a-timestamp/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Rows written in one transaction share an update time to the microsecond. A greater-than cursor drops them and a greater-or-equal cursor repeats them forever.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>A zero tax rate fell through to a hardcoded default, because zero is falsy</title>
      <link>https://sazinga.com/insights/zero-is-a-rate-and-zero-is-falsy/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/zero-is-a-rate-and-zero-is-falsy/</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Three fallbacks in one expression, ending in a statutory rate typed into a route handler. A zero-rated sale skipped the first two and got taxed at the third.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>Five AI providers configured, half the requests failed, and only one was ever tried</title>
      <link>https://sazinga.com/insights/a-200-is-not-a-success/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-200-is-not-a-success/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A fallback chain that advances on error codes but not on empty responses is not a fallback chain. It is one provider with extra configuration.</description>
      <category>ai</category>
    </item>
    <item>
      <title>The click that did nothing was writing to a row nobody reads</title>
      <link>https://sazinga.com/insights/a-lookup-that-returns-an-arbitrary-row/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-lookup-that-returns-an-arbitrary-row/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>An unordered single-row lookup on a non-unique key is not a bug that throws. It is a bug where the user presses a button and the screen ignores them.</description>
      <category>product</category>
    </item>
    <item>
      <title>A pending row is a promise, not a payment</title>
      <link>https://sazinga.com/insights/a-pending-row-is-not-a-payment/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-pending-row-is-not-a-payment/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>The same mistake bit a rental ledger three times in three months — a field naming an amount was read as proof the amount had moved.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>A status only your own app can change will never be true for long</title>
      <link>https://sazinga.com/insights/a-status-only-your-own-app-can-change/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-status-only-your-own-app-can-change/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A dashboard tile read 86 open jobs for one driver. Three were open. The other 83 had ended in ways the app was never told about.</description>
      <category>product</category>
    </item>
    <item>
      <title>A green test nobody has seen fail is not evidence</title>
      <link>https://sazinga.com/insights/a-test-you-have-not-seen-fail/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/a-test-you-have-not-seen-fail/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Seventeen layout tests passed against a stylesheet that made the assertion impossible to fail. Fifty-one screen tests passed on a portal that was entirely read-only.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>An audit log that tells you which events it does not understand yet</title>
      <link>https://sazinga.com/insights/audit-logs-that-find-their-own-gaps/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/audit-logs-that-find-their-own-gaps/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Hand-written audit calls get forgotten, and a forgotten one makes the whole log untrustworthy. Capture centrally, label by registry, and mine the unlabelled.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>Availability is a question about a date, and the picker was answering about today</title>
      <link>https://sazinga.com/insights/availability-is-a-question-about-a-date/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/availability-is-a-question-about-a-date/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A salesperson pitching a campaign that starts next quarter does not care what is free this morning. Availability needs a date argument, not a boolean column.</description>
      <category>product</category>
    </item>
    <item>
      <title>Store everything in UTC, but never decide anything in it</title>
      <link>https://sazinga.com/insights/business-dates-are-not-utc/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/business-dates-are-not-utc/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A test proved expired discounts still applied. The test was wrong, the bug was real, and both came from treating a business date as an instant in time.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Signature scanning found nothing. File integrity found 211 malicious files</title>
      <link>https://sazinga.com/insights/checksums-not-signatures/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/checksums-not-signatures/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A malware scan that returns zero hits is not evidence of a clean site. Comparing files against the official distribution is what actually finds things.</description>
      <category>security</category>
    </item>
    <item>
      <title>67,000 photos already labelled by humans, no GPU, and no model training</title>
      <link>https://sazinga.com/insights/classify-with-labels-you-already-have/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/classify-with-labels-you-already-have/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Embedding existing labelled data into class prototypes gives you a classifier in an afternoon — and a confidence margin that knows when to ask a person.</description>
      <category>ai</category>
    </item>
    <item>
      <title>Making a cross-tenant reference physically impossible with composite foreign keys</title>
      <link>https://sazinga.com/insights/composite-keys-tenant-isolation/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/composite-keys-tenant-isolation/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Tenant isolation enforced by WHERE clauses depends on nobody forgetting one. Enforced by the schema, a cross-tenant row cannot be written at all.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>We deleted four hundred and eighty files before writing a line of the new system</title>
      <link>https://sazinga.com/insights/delete-first-then-rebuild/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/delete-first-then-rebuild/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>An approval step no expense could reach. A module nobody opened. Rebuilding around the real workflow started by removing everything that was not it.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>The cheapest way to secure a brochure site is to stop running an application on it</title>
      <link>https://sazinga.com/insights/deleting-the-application/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/deleting-the-application/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Two compromised sites were rebuilt as static HTML with no interpreter and no database. The attack surface did not shrink — it stopped existing.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>A receivables ledger that was seeded once and then quietly stopped being true</title>
      <link>https://sazinga.com/insights/derive-the-ledger/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/derive-the-ledger/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Two tables held outstanding amounts. Nothing kept them in step with the invoices they came from. Pay an invoice and the ledger never noticed.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>The app was organised like filing cabinets and the people using it were running a process</title>
      <link>https://sazinga.com/insights/filing-cabinets-versus-a-process/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/filing-cabinets-versus-a-process/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Nine modules named after data types. One job — book a hoarding and bill for it — spread across three of them. That is why software feels scattered.</description>
      <category>product</category>
    </item>
    <item>
      <title>A pricing engine where the business owns the formulas and the code owns nothing</title>
      <link>https://sazinga.com/insights/formula-engine-not-hardcoded-rules/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/formula-engine-not-hardcoded-rules/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>362 pricing formulas, none of them in the source code. How to evaluate business-authored expressions without eval, and why that boundary matters.</description>
      <category>pricing</category>
    </item>
    <item>
      <title>They were building the client&apos;s deck by hand in a presentation tool every single time</title>
      <link>https://sazinga.com/insights/generate-the-document-they-already-make-by-hand/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/generate-the-document-they-already-make-by-hand/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A proposal is a slide deck and a cost sheet. Generating both from the same records that produce the booking removes an afternoon of retyping per pitch.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>Never store a balance. Store the entries that produce it</title>
      <link>https://sazinga.com/insights/ledger-not-balance/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/ledger-not-balance/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A mutable points column looks simpler for about a week, and then a retried request pays twice and nobody can explain where the balance came from.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>The first real card payment was credited twice, 434 milliseconds apart</title>
      <link>https://sazinga.com/insights/make-the-claim-the-update/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/make-the-claim-the-update/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A read followed by a check is not a guard. Two webhooks for one payment both passed it, and the customer&apos;s account was credited double the amount.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>The receivables card said zero and the database held forty-five unpaid invoices</title>
      <link>https://sazinga.com/insights/money-that-arrives-as-a-string/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/money-that-arrives-as-a-string/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Fixed-precision money columns come back from the driver as strings. Add them with the wrong operator and the total is silently not a number.</description>
      <category>product</category>
    </item>
    <item>
      <title>The booking rule that blocked eight paying clients, and why it was a bug and not a missing feature</title>
      <link>https://sazinga.com/insights/one-at-a-time-was-a-bug/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/one-at-a-time-was-a-bug/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A digital screen loops six to eight adverts at once. The system allowed one. That is a correctness defect, and it should be sequenced like one.</description>
      <category>product</category>
    </item>
    <item>
      <title>The one convenience that turned a single breach into an estate-wide one</title>
      <link>https://sazinga.com/insights/one-password-many-databases/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/one-password-many-databases/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A shared password reused across every database on a server is not a weak password problem. It removes the boundaries you thought you had.</description>
      <category>security</category>
    </item>
    <item>
      <title>One shared process pool is how a single compromised site reaches all the others</title>
      <link>https://sazinga.com/insights/one-pool-one-breach/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/one-pool-one-breach/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Shared hosting is usually presented as a cost decision. It is a blast-radius decision, and the bill arrives all at once when one site falls.</description>
      <category>security</category>
    </item>
    <item>
      <title>One question, nine implementations, eight of them wrong</title>
      <link>https://sazinga.com/insights/one-question-nine-implementations/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/one-question-nine-implementations/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Who is this leg assigned to? Nine places answered it independently. Eighty-one legs got an arbitrary answer and eighteen invented a driver who was not there.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>How to store a booking that has no end date without breaking every date query you own</title>
      <link>https://sazinga.com/insights/open-ended-without-nulls/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/open-ended-without-nulls/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Runs until the client stops&quot; is a real commercial term. Storing it as a null end date breaks overlap checks, calendars and availability all at once.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Filter the LLM&apos;s tool list by the user&apos;s permissions, not its output</title>
      <link>https://sazinga.com/insights/permission-aware-llm-tools/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/permission-aware-llm-tools/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A model that cannot see a tool cannot call it. Building a natural-language interface where authorisation is structural rather than a prompt instruction.</description>
      <category>ai</category>
    </item>
    <item>
      <title>Read-only sight of money is not authority over it</title>
      <link>https://sazinga.com/insights/permissions-first-roles-second/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/permissions-first-roles-second/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Replacing two hard-coded roles with 77 granular permissions, and the design bug that would have shown field staff the director&apos;s dashboard.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>You finish the booking and the software just stops</title>
      <link>https://sazinga.com/insights/records-that-dead-end/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/records-that-dead-end/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>The data was a chain and the interface was a set of dead ends. No record linked forward to the one it produced, so every step meant going back to a menu.</description>
      <category>product</category>
    </item>
    <item>
      <title>Your permission model probably stops at the ORM and the CSV export walks straight past it</title>
      <link>https://sazinga.com/insights/scope-stops-at-the-csv-writer/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/scope-stops-at-the-csv-writer/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Row-level security kept tenants apart. Nothing kept a branch-scoped user from exporting the entire organisation&apos;s customers, orders and payments.</description>
      <category>security</category>
    </item>
    <item>
      <title>The deposit doubled because the payment landed beside the expectation, not against it</title>
      <link>https://sazinga.com/insights/settle-the-row-do-not-add-one-beside-it/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/settle-the-row-do-not-add-one-beside-it/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A customer paid a five thousand rupee deposit and was immediately asked for it again, because the ledger recorded the receipt as a new row.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>The offline queue marked lost orders as delivered, because every 409 looked the same</title>
      <link>https://sazinga.com/insights/the-409-you-cannot-trust/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-409-you-cannot-trust/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Offline-first only works if the client can tell &quot;already applied&quot; apart from &quot;rejected&quot;. A single conflict status collapses both into one answer.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>The backup job failed silently for four days and four separate things were wrong</title>
      <link>https://sazinga.com/insights/the-backup-that-was-not-running/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-backup-that-was-not-running/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Certificate renewal had been dead for months behind a cron entry that looked like cover. A backup wrote nothing. Neither failure produced a single alert.</description>
      <category>operations</category>
    </item>
    <item>
      <title>The thing you sell is not the thing on the map</title>
      <link>https://sazinga.com/insights/the-bookable-unit/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-bookable-unit/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A hoarding is a location. What a client buys is a surface, for a window, at a rate. Conflating the two puts the overlap check on the wrong row.</description>
      <category>product</category>
    </item>
    <item>
      <title>A permission check that was always false, and why nobody noticed for months</title>
      <link>https://sazinga.com/insights/the-check-that-was-always-false/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-check-that-was-always-false/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A UUID compared against a list of strings is never equal. The check failed closed, denied everything, and looked exactly like correct behaviour.</description>
      <category>security</category>
    </item>
    <item>
      <title>A not-null foreign key is a business rule, and this one was not true</title>
      <link>https://sazinga.com/insights/the-required-key-that-was-a-business-rule/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-required-key-that-was-a-business-rule/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Every invoice had to reference a booking. The business raised invoices without bookings all the time. The constraint had encoded an assumption nobody checked.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Five visitors took the site down for four hours, and the database was idle throughout</title>
      <link>https://sazinga.com/insights/the-site-that-deadlocked-itself/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-site-that-deadlocked-itself/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>An application calling its own API by public hostname consumed two workers per request. At five workers, five simultaneous visitors deadlocked it permanently.</description>
      <category>engineering</category>
    </item>
    <item>
      <title>The soft delete was the bug, not the safety net</title>
      <link>https://sazinga.com/insights/the-soft-delete-was-the-bug/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-soft-delete-was-the-bug/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Keeping a husk row for the audit trail produced phantom drivers on eighteen legs. Deleting the row and logging the change was the safer design.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>Trips completed this month&quot; actually meant &quot;assigned this month</title>
      <link>https://sazinga.com/insights/the-timestamp-that-never-moved/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-timestamp-that-never-moved/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A driver dashboard counted work by a row&apos;s updated timestamp. The timestamp was stamped on insert and had never moved on any of 221 rows.</description>
      <category>product</category>
    </item>
    <item>
      <title>The same extension was charged twice, because a mirrored total has no memory</title>
      <link>https://sazinga.com/insights/the-upstream-total-moved/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/the-upstream-total-moved/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A counter charge and an upstream re-price added the same 1,593 rupees an hour apart. Both stood, and the ledger held back the customer&apos;s deposit for it.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>Two payouts that look identical on a bank statement and must never share a table</title>
      <link>https://sazinga.com/insights/two-payouts-that-look-alike/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/two-payouts-that-look-alike/</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>A co-investor&apos;s profit share and an agency&apos;s introduction commission are both money out to a company. Everything else about them differs.</description>
      <category>data-modelling</category>
    </item>
    <item>
      <title>What Generative Engine Optimisation actually is, and what makes a page citable</title>
      <link>https://sazinga.com/insights/what-is-generative-engine-optimisation/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/what-is-generative-engine-optimisation/</guid>
      <pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate>
      <description>GEO is about being quotable by an answer engine rather than ranked by a search engine, and the two goals reward different things.</description>
      <category>search</category>
    </item>
    <item>
      <title>Stop selling the same billboard twice</title>
      <link>https://sazinga.com/insights/stop-selling-the-same-billboard-twice/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/stop-selling-the-same-billboard-twice/</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <description>Why availability derived from live bookings prevents double-selling in asset businesses, and a spreadsheet inventory structurally cannot.</description>
      <category>operations</category>
    </item>
    <item>
      <title>Offline is a contract, not a feature</title>
      <link>https://sazinga.com/insights/offline-first-field-apps/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/offline-first-field-apps/</guid>
      <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
      <description>Designing field apps for staff with no signal: local-first writes, durable queues, idempotency and conflict rules decided by the business.</description>
      <category>concurrency</category>
    </item>
    <item>
      <title>AI in the delivery loop, described honestly</title>
      <link>https://sazinga.com/insights/ai-in-the-delivery-loop/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/ai-in-the-delivery-loop/</guid>
      <pubDate>Tue, 28 Jul 2026 00:00:00 GMT</pubDate>
      <description>Where AI genuinely speeds up software delivery, where it quietly costs more than it saves, and why review discipline must not loosen.</description>
      <category>ai</category>
    </item>
    <item>
      <title>Why made-to-order manufacturers live in Excel, and what a pricing engine changes</title>
      <link>https://sazinga.com/insights/formula-pricing-for-bespoke-manufacturing/</link>
      <guid isPermaLink="true">https://sazinga.com/insights/formula-pricing-for-bespoke-manufacturing/</guid>
      <pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate>
      <description>Bespoke manufacturers price in spreadsheets for good reasons. A governed pricing engine keeps the flexibility and removes the drift.</description>
      <category>pricing</category>
    </item>
  </channel>
</rss>
