<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Printo Tom</title>
    <description>The latest articles on Forem by Printo Tom (@printo_tom).</description>
    <link>https://forem.com/printo_tom</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3472218%2F8e04e452-db8b-46bb-bc94-b389abc2ae09.png</url>
      <title>Forem: Printo Tom</title>
      <link>https://forem.com/printo_tom</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/printo_tom"/>
    <language>en</language>
    <item>
      <title>Launching *Claude for Legal*: A Toolkit for Modern Legal Workflows</title>
      <dc:creator>Printo Tom</dc:creator>
      <pubDate>Thu, 14 May 2026 13:24:36 +0000</pubDate>
      <link>https://forem.com/printo_tom/launching-claude-for-legal-a-toolkit-for-modern-legal-workflows-4551</link>
      <guid>https://forem.com/printo_tom/launching-claude-for-legal-a-toolkit-for-modern-legal-workflows-4551</guid>
      <description>&lt;p&gt;&lt;strong&gt;Intro:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Legal teams today juggle everything from vendor agreements and privacy impact assessments to litigation prep and law school training. I wanted to create a repo that brings all of these workflows together in one place — practical, extensible, and open for the community. That’s how &lt;em&gt;Claude for Legal&lt;/em&gt; was born.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔑 What’s Inside
&lt;/h3&gt;

&lt;p&gt;This repo is a &lt;strong&gt;comprehensive collection of agents, skills, and connectors&lt;/strong&gt; designed for legal professionals, students, and researchers.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚖️ &lt;strong&gt;Practice‑area plugins&lt;/strong&gt;: In‑house commercial, corporate, employment, privacy, product, regulatory, AI governance, IP, litigation, clinics, and law school.
&lt;/li&gt;
&lt;li&gt;🤖 &lt;strong&gt;Named agents&lt;/strong&gt;: Vendor Agreement Reviewer, DSAR Responder, Claim Chart Builder, Termination Reviewer, NDA Triager, and many more.
&lt;/li&gt;
&lt;li&gt;🔌 &lt;strong&gt;MCP connectors&lt;/strong&gt;: Integrations with Slack, Google Drive, DocuSign, iManage, Everlaw, CourtListener, and other legal‑specific systems.
&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;Managed agent cookbooks&lt;/strong&gt;: Renewal watcher, docket watcher, regulatory feed monitor, diligence grid, launch radar — ready for scheduled deployment.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ⚡ Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accelerates legal analysis&lt;/strong&gt; while keeping attorney review at the center.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured workflows&lt;/strong&gt; with guardrails for compliance, privilege, and risk management.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning tools&lt;/strong&gt; for students and clinics — IRAC graders, case briefers, bar prep coaches, and Socratic drills.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verified citations&lt;/strong&gt; through research connectors like CourtListener and Trellis.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🚀 Getting Started
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Install as a Claude Cowork or Claude Code plugin.
&lt;/li&gt;
&lt;li&gt;Run the &lt;strong&gt;cold‑start interview&lt;/strong&gt; to tailor each plugin to your practice.
&lt;/li&gt;
&lt;li&gt;Connect a research tool for authoritative citations.
&lt;/li&gt;
&lt;li&gt;Explore the scheduled agents for automated monitoring and reporting.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🌟 Why It Matters
&lt;/h3&gt;

&lt;p&gt;The law is evolving fast — privacy, AI governance, regulatory feeds, and litigation workflows all demand agility. This repo helps legal teams and students &lt;strong&gt;move faster without cutting corners&lt;/strong&gt;, combining automation with professional responsibility.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;Explore the repo here:&lt;/strong&gt; &lt;a href="https://github.com/printotomp/claude-legal-assistant-.git" rel="noopener noreferrer"&gt;https://github.com/printotomp/claude-legal-assistant-.git&lt;/a&gt;&lt;br&gt;&lt;br&gt;
I’d love for you to go through it, try the plugins, and share feedback. Contributions are welcome — let’s build the future of legal AI together!&lt;/p&gt;

</description>
      <category>legaltech</category>
      <category>ai</category>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>The AI system that worked in staging destroyed us in production. Here's what we missed.</title>
      <dc:creator>Printo Tom</dc:creator>
      <pubDate>Thu, 14 May 2026 05:30:00 +0000</pubDate>
      <link>https://forem.com/printo_tom/the-ai-system-that-worked-in-staging-destroyed-us-in-production-heres-what-we-missed-28p9</link>
      <guid>https://forem.com/printo_tom/the-ai-system-that-worked-in-staging-destroyed-us-in-production-heres-what-we-missed-28p9</guid>
      <description>&lt;p&gt;I've been a software and enterprise architect for over twelve years. I've shipped pricing platforms, fraud detection systems, and order management infrastructure at scale — most recently at one of the UK's largest retailers. I say that not to flex, but to explain why I'm writing this post with a specific kind of frustration.&lt;/p&gt;

&lt;p&gt;Because almost every article I read about AI in enterprise sounds like it was written by someone who has never been paged at 2am because an LLM-backed pricing rule marked 40,000 product lines as zero.&lt;/p&gt;

&lt;p&gt;So here's what actually happens when you put AI into systems where the decisions have consequences.&lt;/p&gt;

&lt;h2&gt;
  
  
  The staging trap
&lt;/h2&gt;

&lt;p&gt;Staging environments lie. They lie about load, they lie about data shape, and — critically for AI systems — they lie about context drift.&lt;/p&gt;

&lt;p&gt;Context drift is when the world changes between the moment you assembled the input to your model and the moment the model's output takes effect. In a pricing engine, that gap can be milliseconds. In those milliseconds: a competitor might have repriced, a promotional rule might have fired, a stock threshold might have been crossed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What this looks like in practice: your orchestrator assembles context — product cost, margin floor, competitor price, stock level — and sends it to the model. The model reasons and returns a recommended price. Validation passes. But by the time you write to the pricing store, the stock level has changed and the margin floor has been updated by a concurrent batch job. The model's recommendation was correct for a world that no longer exists.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The fix isn't faster models. It's a &lt;strong&gt;snapshot contract&lt;/strong&gt;: a bounded, versioned, immutable view of state captured at orchestration time and passed all the way through to the action layer. Every downstream system confirms against the snapshot version before committing. If the snapshot is stale, you abort and re-orchestrate.&lt;/p&gt;

&lt;p&gt;This pattern is borrowed directly from event sourcing. Most AI architects I've met have never heard of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fraud signals don't behave like pricing signals — and that matters architecturally
&lt;/h2&gt;

&lt;p&gt;One of the most useful things I've done is build &lt;em&gt;both&lt;/em&gt; a fraud detection system and a pricing platform, because the contrast forces architectural clarity.&lt;/p&gt;

&lt;p&gt;Fraud signals are high-frequency, low-latency, and the cost of a false negative is asymmetric — you can recover from a false positive (apologise to a good customer) but you can't unwind a fraudulent transaction. This pushes the architecture toward &lt;strong&gt;fail-closed defaults&lt;/strong&gt;: when confidence is low, decline and escalate.&lt;/p&gt;

&lt;p&gt;Pricing signals are lower frequency, higher context, and the cost structure is different — a bad price for 10 minutes on a low-velocity SKU costs less than a declined checkout. This pushes toward &lt;strong&gt;fail-open defaults&lt;/strong&gt; with aggressive post-hoc monitoring.&lt;/p&gt;

&lt;p&gt;The point is that "AI system" is not a single architecture. The trust posture of your validation layer, your fallback strategy, your human-in-the-loop gates — all of these should be derived from the asymmetry of your failure modes, not from a generic best-practice blog post (including this one).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before you design the system, map your failure modes. A false positive in fraud is not the same as a false positive in pricing. Your architecture should know the difference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The prompt is a contract. Treat it like one.
&lt;/h2&gt;

&lt;p&gt;Your codebase versions your APIs. It versions your database schemas. It does not version your prompts — and that is a production incident waiting to happen.&lt;/p&gt;

&lt;p&gt;We learned this the hard way. A well-intentioned tweak to the system prompt of a fraud classification model changed the output structure enough to break the downstream parser. Silently. For six hours. Because the validation layer was checking for the presence of a field, not its semantic content.&lt;/p&gt;

&lt;p&gt;Prompt versioning isn't complicated. It's a git-tracked file, a version identifier injected into every API call, and a log entry that records which version produced which output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fraud-classifier-v2.4.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-sonnet-4-20250514"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input_snapshot_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"snap_01JV..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"validation_result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"action_taken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"flag_for_review"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every LLM-influenced decision that touches production state should produce a record like this. Not for debugging — for auditability. In retail, in finance, in any regulated domain, the question "why did the system do that?" will be asked by someone whose salary is higher than yours. You want a clean answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The layer nobody builds until they need it
&lt;/h2&gt;

&lt;p&gt;Teams build the orchestration layer. They build the reasoning layer (the model call). They often skip the trust and validation layer, tell themselves they'll add it later, and then spend six months retrofitting it after their first production incident.&lt;/p&gt;

&lt;p&gt;The trust layer is not a safety net. It's load-bearing infrastructure. It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schema enforcement&lt;/strong&gt; — structured output validation before anything downstream sees the result. Not "does the JSON parse" but "does this output satisfy the business constraints it was supposed to satisfy."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidence routing&lt;/strong&gt; — when the model signals uncertainty, the output should not go to production. Route to a fallback rule, a human queue, or a conservative default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic drift detection&lt;/strong&gt; — over time, the distribution of what your model produces drifts. Not because the model changed, but because the world feeding it changed. Monitor output distributions the same way you'd monitor latency percentiles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd tell myself three years ago
&lt;/h2&gt;

&lt;p&gt;The model is not the system. The model is one component inside a system that has to earn the right to touch production state. It earns that right through versioned contracts, explicit validation, bounded context, and audit trails.&lt;/p&gt;

&lt;p&gt;Every shortcut you take on those four things will come back as a production incident. I know because I've taken most of them.&lt;/p&gt;

&lt;p&gt;Build boring AI systems. Your on-call rotation will thank you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you've been through something similar — or disagree with any of this — I'd genuinely like to hear it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
      <category>lessonslearned</category>
    </item>
    <item>
      <title>Choosing the Right Gemma 4 Model: A Practical Guide</title>
      <dc:creator>Printo Tom</dc:creator>
      <pubDate>Mon, 11 May 2026 06:00:00 +0000</pubDate>
      <link>https://forem.com/printo_tom/choosing-the-right-gemma-4-model-a-practical-guide-325p</link>
      <guid>https://forem.com/printo_tom/choosing-the-right-gemma-4-model-a-practical-guide-325p</guid>
      <description>&lt;p&gt;Gemma 4 isn’t just one model — it’s three distinct flavors. Picking the right one can make or break your project.** With Google’s latest open model family, developers now have access to native multimodal capabilities, advanced reasoning, and a massive 128K context window. But the real power lies in choosing the right variant for your use case.&lt;/p&gt;

&lt;p&gt;🧩 The Three Flavors of Gemma 4&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Small (2B / 4B):&lt;br&gt;
Built for ultra‑mobile, edge, and browser deployment. Perfect for IoT projects, mobile apps, or even running on a Raspberry Pi. If you want AI that lives close to the user, this is your pick.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dense (31B):&lt;br&gt;
A powerhouse that bridges server‑grade performance with local execution. Ideal for enterprise prototypes, chatbots, or applications that need strong reasoning without relying on cloud‑only solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mixture‑of‑Experts (26B MoE):&lt;br&gt;
Highly efficient and designed for advanced reasoning at scale. Best suited for research, high‑throughput tasks, or scenarios where efficiency matters as much as raw capability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;⚙️ Practical Scenarios&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Smart Home IoT Assistant → Small Model &lt;br&gt;
Runs locally, respects privacy, and handles multimodal inputs like voice + sensor data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enterprise Knowledge Bot → Dense Model&lt;br&gt;
Balances performance with practicality, enabling long‑context reasoning for business workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Research Reasoning Engine → MoE Model &lt;br&gt;
Efficiently processes complex queries, making it ideal for labs or academic projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Key Insight&lt;/p&gt;

&lt;p&gt;Choosing a model isn’t about “bigger is better.” It’s about &lt;strong&gt;fit for purpose&lt;/strong&gt;. A Raspberry Pi project thrives on the Small model, while a multimodal research tool demands the MoE. Intentional selection shows you understand both the technology and the problem you’re solving.&lt;/p&gt;

&lt;p&gt;📣 Final Thoughts&lt;/p&gt;

&lt;p&gt;Gemma 4 opens the door to local AI that’s powerful, flexible, and accessible. The real challenge — and opportunity — is matching the right model to the right context. Experiment, build, and share your journey with the community. That’s how we’ll unlock the full potential of open AI.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
      <category>ai</category>
    </item>
    <item>
      <title>The Rise of AI-Native Cloud Architectures: Beyond “Lift and Shift”</title>
      <dc:creator>Printo Tom</dc:creator>
      <pubDate>Fri, 08 May 2026 13:29:43 +0000</pubDate>
      <link>https://forem.com/printo_tom/the-rise-of-ai-native-cloud-architectures-beyond-lift-and-shift-1a7d</link>
      <guid>https://forem.com/printo_tom/the-rise-of-ai-native-cloud-architectures-beyond-lift-and-shift-1a7d</guid>
      <description>&lt;p&gt;Cloud isn’t just infrastructure anymore — it’s becoming intelligent.&lt;br&gt;
We’ve moved past the era of simply migrating workloads (“lift and shift”) into the cloud. The new frontier is AI-native cloud architectures — systems designed from the ground up to leverage artificial intelligence as a core capability, not an add-on.&lt;/p&gt;

&lt;p&gt;🌐 What’s Changing?&lt;/p&gt;

&lt;p&gt;• AI at the foundation: Instead of bolting on ML models, platforms like Azure OpenAI and AWS Bedrock are embedding intelligence into orchestration, monitoring, and scaling.&lt;br&gt;
• Self-optimizing workloads: Imagine microservices that auto-tune themselves based on traffic patterns, cost constraints, and user behavior.&lt;br&gt;
• Developer experience redefined: Prompt engineering, AI-assisted coding, and intelligent CI/CD pipelines are becoming standard practice.&lt;/p&gt;

&lt;p&gt;🔑 Why It Matters&lt;/p&gt;

&lt;p&gt;Traditional cloud patterns (containers, serverless, event-driven) solved scalability.&lt;br&gt;
AI-native patterns solve adaptability — systems that learn, predict, and evolve without constant human intervention. This means:&lt;/p&gt;

&lt;p&gt;• Lower operational overhead&lt;br&gt;
• Smarter resource allocation&lt;br&gt;
• Faster innovation cycles&lt;/p&gt;

&lt;p&gt;🛠 Example in Action&lt;/p&gt;

&lt;p&gt;A retail platform running on Azure can now:&lt;/p&gt;

&lt;p&gt;• Predict demand spikes using AI models trained on historical sales + external signals (weather, holidays).&lt;br&gt;
• Auto-scale microservices before the spike hits.&lt;br&gt;
• Adjust pricing dynamically, feeding back into the system for continuous learning.&lt;/p&gt;

&lt;p&gt;This isn’t theory — it’s happening in production today.&lt;/p&gt;

&lt;p&gt;💡 Takeaway&lt;/p&gt;

&lt;p&gt;The future of cloud isn’t just about where you run workloads.&lt;br&gt;
It’s about how intelligently those workloads run themselves.&lt;br&gt;
If you’re designing systems in 2026, ask yourself: Am I building for scale, or am I building for intelligence?&lt;/p&gt;

&lt;p&gt;👉 What do you think — are AI-native architectures the next Kubernetes moment?&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>digitaltransformation</category>
      <category>architecture</category>
      <category>ai</category>
    </item>
    <item>
      <title>How We Caught Fraud Before the Payment Cleared</title>
      <dc:creator>Printo Tom</dc:creator>
      <pubDate>Thu, 30 Apr 2026 06:39:24 +0000</pubDate>
      <link>https://forem.com/printo_tom/how-we-caught-fraud-before-the-payment-cleared-4jcl</link>
      <guid>https://forem.com/printo_tom/how-we-caught-fraud-before-the-payment-cleared-4jcl</guid>
      <description>&lt;p&gt;I want to tell you about the day our fraud system started losing.&lt;br&gt;
Not to fraudsters. To the clock.&lt;br&gt;
We had built what looked, on paper, like a solid fraud detection pipeline. An in-house ML model trained on months of transaction data, a feature store we were proud of, a scoring service sitting neatly between checkout and payment authorisation. Fraud catch rates were good. The data science team was happy.&lt;br&gt;
Then we scaled past a million transactions a day, and everything started to crack.&lt;br&gt;
Not in an obvious, alarms-blaring kind of way. In the quiet, insidious way where your p99 latency creeps up, your SLA breaches start appearing in dashboards nobody checks, and one morning you realise your fraud score is arriving after the payment gateway has already made a decision without it.&lt;br&gt;
This is the story of how we fixed that. And more importantly, what we learned about building real-time fraud systems that actually work at scale — not in a notebook, not in a staging environment, but in production, on millions of real transactions, with real money on the line.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;• Fraud scoring must complete inside the payment authorisation window (~80–120ms available in practice)
• Sequential feature store lookups were our biggest latency killer — parallelising them cut retrieval time by ~60%
• Velocity counters must be pre-aggregated via a stream processor, not computed at request time
• Model inference should run in an isolated sidecar to avoid resource contention
• Always design your fallback scoring path before you need it in an incident
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The constraint nobody puts in the architecture diagram&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is something that doesn’t get written about enough: fraud detection at checkout isn’t a background job. It isn’t something you can do asynchronously and reconcile later. The fraud decision has to fit inside the payment authorisation window — typically somewhere between 150ms and 300ms end-to-end, depending on your payment provider and your checkout UX tolerance.&lt;br&gt;
That window includes network round-trips, payment gateway processing, and your own service calls. By the time your fraud scoring service gets invoked, you might have 80 to 120ms left. Sometimes less.&lt;br&gt;
Miss that window and you have two bad options: block the transaction because you couldn’t score it in time (false positive, frustrated customer, lost revenue), or let it through unscored (potential fraud, chargeback, loss anyway). Neither is acceptable at scale.&lt;/p&gt;

&lt;p&gt;This latency constraint is the architectural forcing function that shapes everything else. It’s not a performance nice-to-have. It’s a hard boundary the entire system has to be designed around from day one.&lt;/p&gt;

&lt;p&gt;We didn’t fully internalise this early enough. That was our first mistake.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the pipeline actually looked like&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before I get into what went wrong, let me walk through how the system was structured — because the architecture itself was sound, and understanding it matters.&lt;br&gt;
When a customer hits checkout, a request comes into our fraud scoring service. That service has one job: take a transaction, produce a risk score between 0 and 1, and do it fast enough to matter.&lt;br&gt;
To produce that score, it needs features — signals about the transaction that the model has learned to interpret. These fall into three categories:&lt;br&gt;
Transaction signals — the basics. Order value, payment method, billing and delivery address match, whether it’s a new card, whether the delivery address has been seen before.&lt;br&gt;
Velocity signals — behavioural patterns over time. How many orders has this account placed in the last hour? Last 24 hours? How many declined payments? Has this device been seen across multiple accounts?&lt;br&gt;
Session and device signals — fingerprinting, typing cadence, how long the customer spent on each page, whether the checkout flow looked human.&lt;br&gt;
Some of these features could be computed in real time. Most couldn’t — not within our latency budget. Velocity counts, account history, device reputation — these needed to be pre-computed and cached in a feature store, ready to be looked up in single-digit milliseconds.&lt;br&gt;
The model itself was a gradient boosted tree — not the most glamorous choice, but interpretable, fast at inference, and well understood by the team. We’d evaluated neural approaches and they weren’t worth the inference overhead for our use case.&lt;br&gt;
The output fed into a decision layer:&lt;br&gt;
Checkout Request&lt;br&gt;
      │&lt;br&gt;
      ▼&lt;br&gt;
Fraud Scoring Service&lt;br&gt;
      │&lt;br&gt;
      ├──► Feature Store ──► account features&lt;br&gt;
      │         │         ──► device features&lt;br&gt;
      │         │         ──► velocity counters&lt;br&gt;
      │         ▼&lt;br&gt;
      ├──► ML Model (gradient boosted tree)&lt;br&gt;
      │         │&lt;br&gt;
      │         ▼  score: 0.0 ──────────── 1.0&lt;br&gt;
      └──► Decision Layer&lt;br&gt;
                │&lt;br&gt;
      ┌─────────┼──────────┐&lt;br&gt;
      ▼         ▼          ▼&lt;br&gt;
   BLOCK    CHALLENGE    ALLOW&lt;br&gt;
  (&amp;gt;0.85)  (0.4–0.85)  (&amp;lt;0.40)&lt;br&gt;
Clean. Logical. And for a while, fine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it started breaking&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Growth is a pressure test. When we were processing hundreds of thousands of transactions a day, our p95 latency was comfortable. The feature store lookups were fast, the model inference was fast, the whole thing felt snappy.&lt;br&gt;
Then volumes grew. And the cracks appeared in a specific order that, in retrospect, told a clear story.&lt;br&gt;
First, our feature store reads started slowing down. Not catastrophically — a few milliseconds here and there. But we were doing multiple lookups per transaction (account-level features, device-level features, velocity counters), and those milliseconds added up. What had been 15ms of feature retrieval became 30ms, then 40ms under peak load.&lt;br&gt;
Second, we discovered that our velocity counters — the “how many orders in the last hour” signals — were being computed differently depending on which service instance handled the request. We had a consistency problem. Different replicas were seeing slightly different views of recent transaction history. The model was being fed subtly wrong features, and we had no idea.&lt;br&gt;
Third, and this was the one that hurt, our model inference time started varying in ways we hadn’t anticipated. A gradient boosted tree should be deterministic and fast — and it was, on average. But at p99, something was happening. JVM garbage collection pauses, resource contention under load, the occasional cold path through the tree for unusual feature combinations.&lt;br&gt;
Our average inference time was 12ms. Our p99 was 47ms.&lt;br&gt;
Add those three problems together and you have a system that works most of the time but fails exactly when you need it most — under peak load, during flash sales, at Christmas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The latency audit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first thing we did was stop guessing and start measuring. Properly measuring.&lt;br&gt;
We instrumented every stage of the pipeline with percentile-level metrics — not just averages, because averages lie in systems like this. We wanted to know what was happening at p95, p99, and p99.9. We added trace IDs to every request so we could follow a single transaction through every hop and see exactly where time was being spent.&lt;br&gt;
What we found surprised us.&lt;br&gt;
The model inference itself was not the primary problem. The real culprit was the feature store lookups — specifically the fact that we were doing them sequentially.&lt;/p&gt;

&lt;p&gt;❌ BEFORE — Sequential lookups&lt;br&gt;
─────────────────────────────────────────────────────&lt;br&gt;
[account lookup 15ms] → [device lookup 15ms] → [velocity lookup 15ms]&lt;br&gt;
= 45ms minimum, 90–120ms under load&lt;br&gt;
─────────────────────────────────────────────────────&lt;/p&gt;

&lt;p&gt;✅ AFTER — Parallel lookups&lt;br&gt;
─────────────────────────────────────────────────────&lt;br&gt;
[account lookup]  ─┐&lt;br&gt;
[device lookup]   ─┼─► all fire simultaneously ─► await all → ~15ms&lt;br&gt;
[velocity lookup] ─┘&lt;br&gt;
─────────────────────────────────────────────────────&lt;br&gt;
With async feature fetching, our retrieval time dropped from the sum of three lookups to the slowest of three lookups — roughly a 60% reduction in that part of the pipeline.&lt;br&gt;
That single change brought us back under SLA. But we didn’t stop there, because we knew it was fragile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we actually rebuilt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once we understood the problem clearly, we made three structural changes that transformed the system’s behaviour under load.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pre-aggregated velocity counters
Rather than computing velocity signals at request time — even with a cache — we moved to a streaming aggregation model. A separate process consumed our transaction event stream and maintained rolling counters in Redis with atomic increments.
By the time a fraud scoring request arrived, the velocity features were already there, updated in real time by the stream processor. The lookup became a simple Redis GET — sub-millisecond, every time.
This also solved the consistency problem. All scoring service instances were now reading from the same source of truth. The subtle feature drift disappeared.&lt;/li&gt;
&lt;li&gt;Model serving as a dedicated sidecar
We moved model inference out of the main scoring service and into a dedicated sidecar process — a lightweight model server running alongside each instance.
This gave us:
• Isolated resource allocation for inference
• Ability to pre-warm the model at startup (no cold path variance)
• Clean separation of concerns — model updates no longer required a full service redeploy
The p99 inference variance dropped significantly. Not because the model changed, but because it was no longer competing for resources with feature retrieval, logging, and everything else the scoring service was doing.&lt;/li&gt;
&lt;li&gt;A hard timeout with a safe fallback
This was the most important thing we did, and it’s the one I see teams most often skip.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We set a hard internal timeout on the fraud scoring pipeline — tighter than the external SLA. If the pipeline didn’t complete within that budget, we applied a pre-computed risk tier based on the customer’s account history instead.&lt;/p&gt;

&lt;p&gt;This meant that even in the worst case — a Redis hiccup, a model serving blip, a network spike — the system degraded gracefully. Transactions still got a risk decision. It just came from a different place.&lt;br&gt;
The fallback was never as accurate as the full model. But it was infinitely better than no decision at all.&lt;/p&gt;

&lt;p&gt;Five things I’d tell any team building this&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with the latency budget, not the model.
Before you write a line of feature engineering code, map out every hop between checkout click and payment authorisation. Know exactly how much time your fraud system has. Build backwards from that constraint.&lt;/li&gt;
&lt;li&gt;Parallelise your feature fetching from day one.
Sequential lookups are a trap. They feel fine at low volume and will absolutely bite you at scale. Async fan-out for feature retrieval is not premature optimisation — it’s table stakes.&lt;/li&gt;
&lt;li&gt;Measure percentiles, not averages.
Your p99 latency is what determines whether you breach SLA under peak load. An average that looks healthy can hide a p99 that’s a disaster. Instrument accordingly.&lt;/li&gt;
&lt;li&gt;Build your fallback before you need it.
Fallback logic written under pressure during an incident is fallback logic that will have bugs. Design your degraded-mode behaviour deliberately, test it, and know exactly what triggers it.&lt;/li&gt;
&lt;li&gt;Feature consistency is a correctness problem, not just a performance problem.
If different instances of your scoring service are seeing different views of the same data, your model is being fed lies. This is hard to detect because everything looks like it’s working — the scores just aren’t quite right. Treat feature consistency as a first-class concern.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What I’d do differently&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I were starting this from scratch, I’d separate the feature store from the scoring service earlier and more aggressively. We treated the feature store as an internal implementation detail for longer than we should have. Making it a proper platform — with clear ownership, explicit SLAs, and a defined contract for the scoring service to consume — would have saved us several painful debugging sessions.&lt;br&gt;
I’d also invest earlier in shadow scoring: running a new model version in parallel against live traffic without acting on its decisions. We did eventually build this, and it transformed our ability to validate model changes safely. But we built it reactively, after a bad model deployment caused a spike in false positives. It should have been part of the platform from the start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Closing thought&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fraud detection at scale is one of those problems that looks straightforward until you’re in it. The ML part — the model, the features, the training pipeline — that’s what gets written about. The infrastructure problem, the latency problem, the question of how you make a confident decision about a transaction in less time than it takes to blink — that’s the part that actually determines whether your system works in production.&lt;br&gt;
Get the architecture right and the model has a chance to do its job. Get it wrong and it doesn’t matter how good your model is.&lt;br&gt;
The clock doesn’t care about your accuracy metrics.&lt;/p&gt;

&lt;p&gt;If you’re building something similar or have dealt with these problems differently, I’d genuinely love to hear about it in the comments. There’s no single right answer here — just tradeoffs, and the specific constraints of your system.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>architecture</category>
      <category>backend</category>
      <category>security</category>
    </item>
    <item>
      <title>How We Built a Real-Time Credit Card Fraud Detection System: An Architect's Perspective</title>
      <dc:creator>Printo Tom</dc:creator>
      <pubDate>Mon, 27 Apr 2026 07:17:45 +0000</pubDate>
      <link>https://forem.com/printo_tom/how-we-built-a-real-time-credit-card-fraud-detection-system-an-architects-perspective-4ib7</link>
      <guid>https://forem.com/printo_tom/how-we-built-a-real-time-credit-card-fraud-detection-system-an-architects-perspective-4ib7</guid>
      <description>&lt;p&gt;Every millisecond counts when it comes to fraud. A fraudulent transaction approved in 200ms costs real money. A legitimate transaction declined in 200ms costs a customer. Getting this balance right — at scale — is one of the hardest engineering problems in financial services.&lt;/p&gt;

&lt;p&gt;This is a deep dive into the architectural decisions, trade-offs, and hard lessons from building a production-grade credit card fraud detection system. No toy datasets. No Jupyter notebooks. Real architecture, real constraints.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Is Not What You Think
&lt;/h2&gt;

&lt;p&gt;Most tutorials frame fraud detection as a machine learning problem. Pick the right model, tune your F1 score, ship it. &lt;/p&gt;

&lt;p&gt;In production, it's an &lt;strong&gt;engineering and systems problem&lt;/strong&gt; with ML embedded inside it.&lt;/p&gt;

&lt;p&gt;The real challenges are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Latency: you have ~150–300ms to make a decision before the payment network times out&lt;/li&gt;
&lt;li&gt;Scale: millions of transactions per day, with spikes you cannot always predict&lt;/li&gt;
&lt;li&gt;Imbalance: fraudulent transactions can be as low as 0.1% of total volume — your system must be hypersensitive to a signal buried in 99.9% noise&lt;/li&gt;
&lt;li&gt;Drift: fraud patterns change constantly; yesterday's model is today's liability&lt;/li&gt;
&lt;li&gt;Explainability: regulators and customers will ask &lt;em&gt;why&lt;/em&gt; a transaction was declined&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are model problems. All of them are architecture problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  System Architecture: The Big Picture
&lt;/h2&gt;

&lt;p&gt;Here's the high-level design we settled on after several iterations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transaction Request
       │
       ▼
┌─────────────────────┐
│   API Gateway        │  ← Rate limiting, auth, routing
└────────┬────────────┘
         │
         ▼
┌─────────────────────┐
│  Feature Service     │  ← Real-time feature assembly (&amp;lt;20ms)
│  (Redis + Flink)     │
└────────┬────────────┘
         │
         ▼
┌─────────────────────┐
│  Scoring Engine      │  ← ML model inference (&amp;lt;50ms)
│  (Rule layer +       │
│   ML model layer)    │
└────────┬────────────┘
         │
         ▼
┌─────────────────────┐
│  Decision Engine     │  ← Threshold logic, risk bands, actions
└────────┬────────────┘
         │
    ┌────┴─────┐
    ▼          ▼
 Approve    Decline / Step-up (3DS)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entire synchronous path — from transaction in to decision out — must complete in under 300ms. Everything else (model retraining, alerting, feedback loops) is asynchronous.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1: Feature Engineering is Everything
&lt;/h2&gt;

&lt;p&gt;The biggest performance gains we saw did not come from switching models — they came from better features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-Time Features (assembled per transaction)
&lt;/h3&gt;

&lt;p&gt;These are computed on-the-fly and pulled from Redis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Velocity features&lt;/strong&gt;: number of transactions in last 1m / 5m / 1h / 24h per card&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amount deviation&lt;/strong&gt;: how far this transaction deviates from the cardholder's average spend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merchant risk score&lt;/strong&gt;: pre-computed score for the merchant category / MCC code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-of-day signal&lt;/strong&gt;: is this transaction outside the cardholder's normal hours?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geographic anomaly&lt;/strong&gt;: is the country/city inconsistent with recent usage?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Behavioural Baseline Features (batch, updated hourly)
&lt;/h3&gt;

&lt;p&gt;Pulled from a feature store (we used Feast, but Redis + Spark works too):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;30-day average transaction amount&lt;/li&gt;
&lt;li&gt;Typical merchant categories&lt;/li&gt;
&lt;li&gt;Device fingerprint history&lt;/li&gt;
&lt;li&gt;Known trusted locations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Hard Part: Consistency
&lt;/h3&gt;

&lt;p&gt;The training data must use &lt;strong&gt;exactly the same feature definitions&lt;/strong&gt; as inference. Feature drift between training and serving is one of the most common sources of degraded model performance in production — and it's invisible until something breaks.&lt;/p&gt;

&lt;p&gt;We solved this by owning feature computation in a shared library used by both the batch training pipeline and the real-time feature service. Same code. No exceptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 2: The Scoring Engine — Rules + ML Together
&lt;/h2&gt;

&lt;p&gt;We ran two scoring layers in parallel, not in sequence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rules Engine (first line of defence)
&lt;/h3&gt;

&lt;p&gt;Simple, fast, interpretable. Handles obvious cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="n"&gt;transaction_country&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="n"&gt;cardholder_known_countries&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;hour_of_day&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rules are cheap to update, easy to explain to regulators, and handle known fraud patterns with high precision. They block roughly 30–40% of fraud before the ML model is even invoked.&lt;/p&gt;

&lt;h3&gt;
  
  
  ML Model Layer
&lt;/h3&gt;

&lt;p&gt;We landed on a &lt;strong&gt;gradient boosted tree&lt;/strong&gt; (XGBoost) as the primary model, for three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt;: inference is sub-millisecond even with 200+ features&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: consistently outperforms neural networks on tabular transaction data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explainability&lt;/strong&gt;: SHAP values give you per-prediction feature importance, which is gold for compliance teams&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We also ran a secondary &lt;strong&gt;autoencoder-based anomaly detector&lt;/strong&gt; in parallel for catching novel fraud patterns the supervised model had never seen. Its score was blended in with a lower weight.&lt;/p&gt;

&lt;h3&gt;
  
  
  Class Imbalance: What Actually Works
&lt;/h3&gt;

&lt;p&gt;The standard advice is to use SMOTE or random oversampling. In practice, we found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SMOTE helped during initial model development&lt;/strong&gt; but added noise at high volumes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost-sensitive learning&lt;/strong&gt; (setting &lt;code&gt;scale_pos_weight&lt;/code&gt; in XGBoost) was more robust in production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Threshold tuning&lt;/strong&gt; post-training gave us far more control over the precision-recall trade-off than any resampling technique&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not optimise for accuracy. Optimise for &lt;strong&gt;precision-recall AUC&lt;/strong&gt; and then tune your operating threshold based on business risk appetite.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 3: The Decision Engine
&lt;/h2&gt;

&lt;p&gt;The model outputs a score between 0 and 1. The decision engine translates that into an action:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Score Band&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.0 – 0.3&lt;/td&gt;
&lt;td&gt;Approve&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.3 – 0.6&lt;/td&gt;
&lt;td&gt;Approve with soft alert&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.6 – 0.8&lt;/td&gt;
&lt;td&gt;Step-up authentication (3DS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.8 – 1.0&lt;/td&gt;
&lt;td&gt;Decline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These thresholds are &lt;strong&gt;not fixed&lt;/strong&gt;. They shift based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Merchant risk profile&lt;/strong&gt;: a high-risk merchant (e.g., crypto exchange, gift cards) shifts the threshold down&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time of day / fraud rate spikes&lt;/strong&gt;: during known high-fraud periods, thresholds tighten&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Card holder profile&lt;/strong&gt;: a known high-value customer might get a softer threshold to protect against false positives&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dynamic thresholding layer is where a lot of the business logic lives, and it's deliberately kept separate from the ML model so it can be tuned without retraining.&lt;/p&gt;




&lt;h2&gt;
  
  
  Model Retraining: The Feedback Loop Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;A fraud model trained on 6-month-old data is already becoming stale. Fraud rings adapt quickly.&lt;/p&gt;

&lt;p&gt;Our retraining pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Daily batch&lt;/strong&gt;: new confirmed fraud labels (from manual review + chargeback signals) are fed into the training dataset&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weekly retrain&lt;/strong&gt;: model is retrained on a rolling 90-day window&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shadow scoring&lt;/strong&gt;: new model runs in shadow mode alongside production for 48 hours before promotion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canary release&lt;/strong&gt;: new model serves 5% of traffic before full rollout, with automatic rollback if key metrics degrade&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key metric we watched during shadow mode was &lt;strong&gt;rank order&lt;/strong&gt; — does the new model score known fraudulent transactions higher than known legitimate ones? A lift chart drift of more than 5% triggered a human review.&lt;/p&gt;




&lt;h2&gt;
  
  
  Infrastructure Choices and Why
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Feature cache&lt;/td&gt;
&lt;td&gt;Redis Cluster&lt;/td&gt;
&lt;td&gt;Sub-millisecond read latency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stream processing&lt;/td&gt;
&lt;td&gt;Apache Flink&lt;/td&gt;
&lt;td&gt;Stateful windowed aggregations at scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model serving&lt;/td&gt;
&lt;td&gt;Custom FastAPI service&lt;/td&gt;
&lt;td&gt;Full control over batching and concurrency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Feature store&lt;/td&gt;
&lt;td&gt;Feast&lt;/td&gt;
&lt;td&gt;Consistency between training and serving&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monitoring&lt;/td&gt;
&lt;td&gt;Prometheus + Grafana&lt;/td&gt;
&lt;td&gt;Real-time score distribution and drift alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Experiment tracking&lt;/td&gt;
&lt;td&gt;MLflow&lt;/td&gt;
&lt;td&gt;Model versioning and reproducibility&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We deliberately avoided "full-stack" ML platforms that bundle everything together. The lock-in risk and latency overhead were not worth the developer experience gains at our scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We Got Wrong (and Fixed)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. We underestimated feature latency
&lt;/h3&gt;

&lt;p&gt;Early on, our feature service was querying a relational database. At peak load, this added 80–120ms to the decision path — completely unacceptable. Migrating feature reads to Redis brought this down to 3–5ms.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. We over-rotated to ML and abandoned rules
&lt;/h3&gt;

&lt;p&gt;A period where the ML model was doing all the heavy lifting meant that when it degraded (due to data drift), there was no backstop. Bringing the rules layer back as a first gate significantly improved resilience.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. We optimised the wrong metric
&lt;/h3&gt;

&lt;p&gt;In early iterations, we chased high recall (catch as much fraud as possible). This led to a false positive rate that was frustrating legitimate cardholders. The right trade-off is business-specific — understand your chargeback cost vs. your customer attrition cost before setting thresholds.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. We didn't monitor score distributions
&lt;/h3&gt;

&lt;p&gt;A model can look healthy on offline metrics while its live score distribution is silently shifting. We now track percentile distribution of scores daily. Any unexpected shift triggers an investigation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Latency is a hard constraint&lt;/strong&gt;, not a nice-to-have. Design your feature assembly and inference path first, then fit your model choices around it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rules + ML is better than ML alone&lt;/strong&gt; — rules handle known patterns, ML catches the novel ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature engineering and consistency&lt;/strong&gt; between training and serving will give you more performance gains than model selection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor score distributions in production&lt;/strong&gt;, not just model metrics on a test set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate your decision logic from your model&lt;/strong&gt; — thresholds and business rules change faster than models, and that's okay.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fraud detection is a live arms race. The system that catches fraud today will need to evolve to catch fraud tomorrow. Build for adaptability, not just accuracy.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you built fraud detection systems? I'd love to hear what architectural decisions you made differently — drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>machinelearning</category>
      <category>fintech</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Google Cloud NEXT '26 Just Changed How I Think About Real-Time Pricing APIs</title>
      <dc:creator>Printo Tom</dc:creator>
      <pubDate>Sat, 25 Apr 2026 06:44:26 +0000</pubDate>
      <link>https://forem.com/printo_tom/google-cloud-next-26-just-changed-how-i-think-about-real-time-pricing-apis-3i3m</link>
      <guid>https://forem.com/printo_tom/google-cloud-next-26-just-changed-how-i-think-about-real-time-pricing-apis-3i3m</guid>
      <description>&lt;p&gt;I've been building Pricing APIs for years.&lt;/p&gt;

&lt;p&gt;And if you've ever built one — a real one, one that has to serve millions of customers, react to stock levels, competitor moves, time of day, demand surges, and promotional calendars — you know the dirty secret at the heart of most of them.&lt;/p&gt;

&lt;p&gt;They're not really real-time.&lt;/p&gt;

&lt;p&gt;They're very fast batch jobs wearing a real-time costume.&lt;/p&gt;

&lt;p&gt;You precompute prices on a schedule. You cache aggressively. You serve stale data with enough confidence that most customers never notice. And you spend half your architectural energy managing the gap between "what the price should be right now" and "what the price actually says right now."&lt;/p&gt;

&lt;p&gt;I've been sitting with that problem for a long time. Then Google Cloud NEXT '26 happened. And something clicked.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Google Just Announced (And Why It's Not What You Think)
&lt;/h2&gt;

&lt;p&gt;The big headline from NEXT '26 is the &lt;strong&gt;Gemini Enterprise Agent Platform&lt;/strong&gt; — Google's full rebranding of Vertex AI into an end-to-end system for building, scaling, governing, and optimising autonomous AI agents.&lt;/p&gt;

&lt;p&gt;Most people read that as an enterprise productivity story. Automate your emails. Summarise your meetings. Build a chatbot for HR.&lt;/p&gt;

&lt;p&gt;I read it as an infrastructure story. Specifically, as the missing architectural layer that makes a genuinely real-time Pricing API actually buildable — without a team of 20 people and a multi-year runway.&lt;/p&gt;

&lt;p&gt;Let me walk you through what I mean.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem With Pricing APIs
&lt;/h2&gt;

&lt;p&gt;Picture Black Friday. 9:00 AM.&lt;/p&gt;

&lt;p&gt;Your traffic spikes 40x in 90 seconds. Your inventory for a flagship product drops from 10,000 units to 200 in the time it takes to read this sentence. A competitor just dropped their price by 15%. Three promotional campaigns are live simultaneously. Your demand forecasting model is screaming that stock will hit zero in 11 minutes.&lt;/p&gt;

&lt;p&gt;What should the price be &lt;em&gt;right now&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Not in 5 minutes when your next batch job runs. Not based on the snapshot from 3 minutes ago. Right now.&lt;/p&gt;

&lt;p&gt;In most systems I've worked with, nobody actually knows. The system serves whatever it last computed and hopes for the best.&lt;/p&gt;

&lt;p&gt;The problem isn't compute. It's &lt;strong&gt;orchestration&lt;/strong&gt;. Getting five different signals — inventory, competitor pricing, demand velocity, promotional state, customer segment — to converge on a single decision, in milliseconds, at scale, without hard-coding every possible combination of conditions.&lt;/p&gt;

&lt;p&gt;That's not a caching problem. That's a reasoning problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Gemini Enterprise Agent Platform Changes the Game
&lt;/h2&gt;

&lt;p&gt;Here's what caught my attention at NEXT '26.&lt;/p&gt;

&lt;p&gt;Google announced the &lt;strong&gt;Agentic Data Cloud&lt;/strong&gt; — a new way of organising enterprise data so that AI agents can take action on it in real time. At the centre of it is something called the &lt;strong&gt;Knowledge Catalog&lt;/strong&gt;: a live, AI-maintained map of your entire data estate, automatically tagged and connected so agents understand the context and relationships between your systems.&lt;/p&gt;

&lt;p&gt;For a Pricing API, think about what that means.&lt;/p&gt;

&lt;p&gt;Today, your pricing logic has to explicitly know about the relationship between your inventory system, your competitor feed, your promotions database, and your demand model. Someone had to write that understanding into code. Someone has to maintain it when things change. Every new data source is a sprint.&lt;/p&gt;

&lt;p&gt;With a Knowledge Catalog backed by Gemini, your pricing agent doesn't need to be told "when inventory drops below 5%, check the demand velocity signal before adjusting price." It can reason over your connected data estate and arrive at that logic itself — and update its reasoning as your business changes, without a redeploy.&lt;/p&gt;

&lt;p&gt;That's a fundamentally different model.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Gemini-Powered Pricing API Looks Like
&lt;/h2&gt;

&lt;p&gt;Let me make this concrete. Here's how I'd architect a real-time pricing system on the Gemini Enterprise Agent Platform, using what was announced this week.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pricing Agent
&lt;/h3&gt;

&lt;p&gt;Built on the &lt;strong&gt;Agent Development Kit (ADK)&lt;/strong&gt;, the Pricing Agent is a persistent, long-running agent that owns pricing decisions for a product catalogue. It's not a model you call once per request. It's a stateful entity with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory Bank&lt;/strong&gt; (now GA): persistent context about each product's pricing history, demand patterns, and the reasoning behind previous decisions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Identity&lt;/strong&gt;: a verified, auditable identity that allows the pricing agent to call authorised tools — pulling from your inventory system, your competitor feed, your ERP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-agent coordination&lt;/strong&gt;: sub-agents for inventory monitoring, competitor scraping, and promotional eligibility can push updates to the pricing agent in real time, rather than waiting to be polled&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Real-Time Signal Layer
&lt;/h3&gt;

&lt;p&gt;This is where the &lt;strong&gt;Agentic Data Cloud&lt;/strong&gt; and the &lt;strong&gt;Cross-Cloud Lakehouse&lt;/strong&gt; (built on Apache Iceberg) come in. Your data doesn't have to move. Your inventory lives in your warehouse system. Your competitor feed lives wherever it lives. The Knowledge Catalog maps the relationships, and the pricing agent queries across them with zero data migration.&lt;/p&gt;

&lt;p&gt;On Black Friday at 9:00 AM, the inventory sub-agent fires an event: "Product X — 200 units remaining, sell-through rate 18 units/minute." That event hits the pricing agent's inbox. The agent has context (from Memory Bank) that this product has a 94% attachment rate with a premium customer segment. It checks the promotional state. It queries the competitor feed sub-agent. And it issues a price update within the decision window — not because a rule said so, but because it reasoned to that outcome.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Governance Layer
&lt;/h3&gt;

&lt;p&gt;This is the part that most AI architecture conversations skip. You cannot have an autonomous agent making live pricing decisions without an audit trail, human oversight triggers, and rollback capability.&lt;/p&gt;

&lt;p&gt;The Gemini Enterprise Agent Platform has this built in. &lt;strong&gt;Agent Engine&lt;/strong&gt; provides observability into every decision the agent makes — what signals it considered, what it decided, why. For regulated environments (and retail pricing absolutely counts), this auditability is non-negotiable.&lt;/p&gt;

&lt;p&gt;You can also define confidence thresholds: if the pricing agent's recommendation falls outside a predefined band, it doesn't auto-apply — it routes to a human for approval. That's not a limitation. That's the right architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Part That Actually Surprised Me
&lt;/h2&gt;

&lt;p&gt;I expected the agent platform announcement. I did not expect the &lt;strong&gt;managed MCP servers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Google announced managed Model Context Protocol (MCP) servers across Google Cloud services. For those unfamiliar, MCP is the protocol that lets AI agents call external tools in a standardised way — think of it as USB-C for AI integrations.&lt;/p&gt;

&lt;p&gt;What this means for a Pricing API is that your agent can call your authorised pricing tools — apply discount, update price, trigger campaign — through a governed, observable, rate-limited interface. No custom integration work. No bespoke API wrappers. Just a standard protocol your agent speaks natively.&lt;/p&gt;

&lt;p&gt;Combined with the &lt;strong&gt;A2A (Agent-to-Agent) protocol&lt;/strong&gt; also announced this week, your pricing agent can directly coordinate with a fulfilment agent, a customer service agent, and a demand forecasting agent — across platforms, not just within Google Cloud. That's the multi-agent mesh that enterprise systems have needed for a decade.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Build First
&lt;/h2&gt;

&lt;p&gt;If I were starting a new Pricing API project tomorrow, here's where I'd begin on this stack:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Week 1–2: Knowledge Catalog setup&lt;/strong&gt;&lt;br&gt;
Map your pricing-relevant data — inventory, promotions, competitor feeds, customer segments — into the Knowledge Catalog. Let Gemini tag the relationships. Don't write the logic yourself. Observe what it surfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Week 3–4: Single-product pilot agent&lt;/strong&gt;&lt;br&gt;
Build a pricing agent for one product category using ADK. Give it read access to your inventory and competitor signals via MCP tools. Run it in shadow mode — it makes recommendations, humans apply them. Compare to your current pricing outcomes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Week 5–6: Governance baseline&lt;/strong&gt;&lt;br&gt;
Define your guardrails before you go live. Price floor/ceiling bounds. Confidence thresholds. Escalation paths. Audit log review cadence. This is the work that makes the business trust the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month 2 onward: Expand and measure&lt;/strong&gt;&lt;br&gt;
Roll out to more categories. Track margin impact, stock turn rate, competitive win rate. The agent gets better as Memory Bank accumulates context. That's the flywheel.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Honest Take
&lt;/h2&gt;

&lt;p&gt;I'm genuinely excited about what Google announced this week. The Gemini Enterprise Agent Platform, the Agentic Data Cloud, managed MCP servers, A2A — these aren't incremental updates. They're the connective tissue that enterprise AI has been missing.&lt;/p&gt;

&lt;p&gt;But I want to be honest about what this isn't, yet.&lt;/p&gt;

&lt;p&gt;Building a production-grade pricing agent still requires you to own the domain logic. You have to define what "correct pricing" means for your business. You have to set the guardrails. You have to decide when the agent decides autonomously and when a human is in the loop. The platform gives you the infrastructure. The thinking is still yours.&lt;/p&gt;

&lt;p&gt;And that's actually how it should be.&lt;/p&gt;

&lt;p&gt;Pricing is a competitive moat. The businesses that will win with this technology are not the ones who hand the decisions entirely to an agent. They're the ones who use agents to act faster on better information — while keeping the strategic reasoning close to home.&lt;/p&gt;

&lt;p&gt;That's always been the job of architecture. It's just got a lot more interesting.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you worked on real-time pricing systems? I'd love to hear how you're thinking about agents in this space — drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>cloudnextchallenge</category>
      <category>googlecloud</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Building a Pricing Engine That Actually Works at Scale</title>
      <dc:creator>Printo Tom</dc:creator>
      <pubDate>Thu, 23 Apr 2026 12:45:34 +0000</pubDate>
      <link>https://forem.com/printo_tom/building-a-pricing-engine-that-actually-works-at-scale-486f</link>
      <guid>https://forem.com/printo_tom/building-a-pricing-engine-that-actually-works-at-scale-486f</guid>
      <description>&lt;h1&gt;
  
  
  Building a Pricing Engine That Actually Works at Scale
&lt;/h1&gt;

&lt;p&gt;Most people think pricing is simple.&lt;/p&gt;

&lt;p&gt;Set a price → show it → done.&lt;/p&gt;

&lt;p&gt;But the moment you deal with real traffic, real users, and real business pressure… things get messy very quickly.&lt;/p&gt;

&lt;p&gt;I’ve worked on systems where pricing wasn’t just a number — it was something that had to react in real time to inventory, demand, and campaigns. And honestly, that’s where things get interesting.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem nobody talks about
&lt;/h2&gt;

&lt;p&gt;Traditional pricing systems are slow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prices updated every few hours
&lt;/li&gt;
&lt;li&gt;Hardcoded rules
&lt;/li&gt;
&lt;li&gt;No flexibility
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That works… until:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traffic spikes
&lt;/li&gt;
&lt;li&gt;Inventory changes every minute
&lt;/li&gt;
&lt;li&gt;Business wants instant campaign updates
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At that point, the system starts breaking.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually needs to happen
&lt;/h2&gt;

&lt;p&gt;A modern pricing system needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Respond in milliseconds
&lt;/li&gt;
&lt;li&gt;Handle huge traffic (millions of requests)
&lt;/li&gt;
&lt;li&gt;Stay available even under load
&lt;/li&gt;
&lt;li&gt;Adapt quickly to business changes
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which means — you can’t treat it like a simple backend service.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I think about the architecture
&lt;/h2&gt;

&lt;p&gt;Instead of one big system, you break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A service that handles pricing requests
&lt;/li&gt;
&lt;li&gt;A rules layer that controls logic (discounts, campaigns, etc.)
&lt;/li&gt;
&lt;li&gt;A data layer for inventory + product info
&lt;/li&gt;
&lt;li&gt;A messaging system (Kafka/RabbitMQ) to push updates in real time
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key idea:&lt;/p&gt;

&lt;p&gt;👉 Don’t pull data. React to events.&lt;/p&gt;

&lt;p&gt;When inventory changes → pricing updates&lt;br&gt;&lt;br&gt;
When campaigns change → pricing updates  &lt;/p&gt;

&lt;p&gt;That shift alone changes everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real challenges (not theory)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Latency kills everything
&lt;/h3&gt;

&lt;p&gt;If your pricing call takes too long, the whole user experience suffers.&lt;/p&gt;

&lt;p&gt;So you end up using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caching (a lot of it)
&lt;/li&gt;
&lt;li&gt;Precomputed values
&lt;/li&gt;
&lt;li&gt;Smart fallbacks
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Nothing is ever “clean”
&lt;/h3&gt;

&lt;p&gt;In real systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data is inconsistent
&lt;/li&gt;
&lt;li&gt;Dependencies break
&lt;/li&gt;
&lt;li&gt;Edge cases show up daily
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t design for perfection — you design for failure.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Business moves faster than code
&lt;/h3&gt;

&lt;p&gt;This is the hardest part.&lt;/p&gt;

&lt;p&gt;The business wants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New campaigns tomorrow
&lt;/li&gt;
&lt;li&gt;Pricing changes instantly
&lt;/li&gt;
&lt;li&gt;Experiments running all the time
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So your system has to be flexible, not just scalable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where AI starts coming in
&lt;/h2&gt;

&lt;p&gt;Now things are evolving.&lt;/p&gt;

&lt;p&gt;Pricing is no longer just rules-based.&lt;/p&gt;

&lt;p&gt;You start seeing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Demand prediction
&lt;/li&gt;
&lt;li&gt;Competitor-based adjustments
&lt;/li&gt;
&lt;li&gt;Dynamic pricing models
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But even then — the architecture still matters more than the model.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;The biggest lesson for me:&lt;/p&gt;

&lt;p&gt;👉 Pricing systems are not about pricing.&lt;/p&gt;

&lt;p&gt;They’re about building a system that can handle constant change without breaking.&lt;/p&gt;

&lt;p&gt;And that’s where most designs fail.&lt;/p&gt;




&lt;p&gt;If you’ve worked on similar systems, I’m curious — what was the hardest part for you?&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>microservices</category>
      <category>architecture</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
