<?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>DEV Community: Mariano Barcia</title>
    <description>The latest articles on DEV Community by Mariano Barcia (@mbarcia).</description>
    <link>https://dev.to/mbarcia</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3186852%2Fc12e3db2-bbe9-47ea-86d4-bfad00f15c5d.JPG</url>
      <title>DEV Community: Mariano Barcia</title>
      <link>https://dev.to/mbarcia</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mbarcia"/>
    <language>en</language>
    <item>
      <title>HappyGF: I Built an AI Assistant to Make Sure Contractors Get Paid on Friday</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Mon, 19 Oct 2026 05:09:25 +0000</pubDate>
      <link>https://dev.to/mbarcia/happygf-i-built-an-ai-assistant-to-make-sure-contractors-get-paid-on-friday-o14</link>
      <guid>https://dev.to/mbarcia/happygf-i-built-an-ai-assistant-to-make-sure-contractors-get-paid-on-friday-o14</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Every Friday, the accountant processes payments to the contractors and suppliers who keep my girlfriend's business running. For that to happen, invoices need to be received, reviewed, approved, correctly named, and forwarded to the accountant before the deadline.&lt;/p&gt;

&lt;p&gt;It sounds straightforward, until you consider how many invoices arrive by email, often from different contractors, in different formats, with different naming conventions—or none at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8dr2o3s1go28oao8v2m6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8dr2o3s1go28oao8v2m6.png" alt="Invoice sent" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The accountant requires PDF filenames containing the vendor, property, and invoice amount, following a specific convention. My girlfriend was spending far too much time opening attachments, checking details, renaming files, and forwarding them. Worse, mistakes or delays could mean someone didn't get paid that Friday.&lt;/p&gt;

&lt;p&gt;That's how &lt;strong&gt;HappyGF&lt;/strong&gt;, an AI-powered accounts payable assistant, came about.&lt;/p&gt;

&lt;p&gt;The application helps her process incoming vendor invoices, extract the relevant information, prepare correctly named PDFs, and get approved invoices ready for the accountant.&lt;/p&gt;

&lt;p&gt;It also remembers what has already been processed. Recently, a contractor accidentally submitted the same invoice twice. HappyGF recognized the duplicate instead of treating it as another invoice to process. A small detail, perhaps, but an important one when dealing with payments.&lt;/p&gt;

&lt;p&gt;This isn't an experiment looking for a use case. She's already using the application for real work, and I'm now releasing an open-source edition for other businesses dealing with similar accounts payable workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Video:&lt;/strong&gt; &lt;a href="https://youtu.be/Ttzg6bqgyA8" rel="noopener noreferrer"&gt;https://youtu.be/Ttzg6bqgyA8&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The demonstration uses fictional vendors, properties, and invoices to show the workflow from incoming email to an accountant-ready PDF.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/MokapotLabs/invoice-assistant" rel="noopener noreferrer"&gt;https://github.com/MokapotLabs/invoice-assistant&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The open-source edition includes the application, configuration, tests, and instructions for running it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;HappyGF is written in Java using &lt;a href="https://pipelineframework.org/" rel="noopener noreferrer"&gt;The Pipeline Framework (TPF)&lt;/a&gt;, an open-source framework I've been developing over the past few years.&lt;/p&gt;

&lt;p&gt;One thing I learned along the way is that not every AI task needs the same model. Reading an unfamiliar invoice, recognizing a company logo, and deciding which property an invoice belongs to are different problems.&lt;/p&gt;

&lt;p&gt;The open-source edition uses three models through Ollama:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Qwen 3.5 4B&lt;/strong&gt; for invoice text analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qwen3-VL 4B&lt;/strong&gt; for visual recognition, including company logos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tev1&lt;/strong&gt; for structured supplier and property decisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tev1 is particularly interesting. It's a small, open-weight decision model that uses the same Jev-style API as the hosted decision service I've been using. Rather than asking a generative model to produce another paragraph of text, the application can ask a specific question, supply possible answers, and receive a structured decision.&lt;/p&gt;

&lt;p&gt;Once the invoice has been interpreted, ordinary application code applies the filename convention, tracks processing state, detects duplicates, and manages the approval workflow. The AI assists with interpretation; it doesn't get to authorize payments or bypass business rules.&lt;/p&gt;

&lt;p&gt;Microsoft Graph provides the Outlook integration, while TPF handles the typed pipelines, persistence, external operations, and execution concerns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local AI sounded perfect. Then I tried running it on an 8 GB MacBook.
&lt;/h3&gt;

&lt;p&gt;My original intention was to keep inference local, using Ollama. It works, and I've used it extensively for development and automated testing.&lt;/p&gt;

&lt;p&gt;Unfortunately, the application isn't something my girlfriend uses continuously. She opens it when there are invoices to process, and Ollama may need to load the models into memory. Some invoices also require visual recognition, which means switching models.&lt;/p&gt;

&lt;p&gt;On her 8 GB MacBook, that can turn into a one- or two-minute wait. Not exactly the experience you want when you're trying to get through a pile of invoices before Friday.&lt;/p&gt;

&lt;p&gt;Running Ollama on another machine would help, but keeping another computer running just to process a few invoices each week feels rather wasteful.&lt;/p&gt;

&lt;p&gt;So I tried hosted inference through OpenRouter.&lt;/p&gt;

&lt;p&gt;The current hosted setup uses &lt;strong&gt;Gemini 3.1 Flash Lite and Jev 1.13&lt;/strong&gt;. It's fast, requires no local model installation, and the API key has accumulated less than four US cents in usage so far.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq71w5zim6fvcyu9kg2yj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq71w5zim6fvcyu9kg2yj.png" alt="OpenRouter usage" width="800" height="885"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Introducing Jev also made a noticeable difference to cost. By moving suitable decisions away from the generative model, I've seen roughly a 50% reduction in inference spending.&lt;/p&gt;

&lt;p&gt;These are observations from a lightly used application, not a controlled benchmark, but they surprised me. At this volume, inference costs are practically negligible compared with the time saved.&lt;/p&gt;

&lt;p&gt;The open-source edition retains Ollama support, so users can choose local inference instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;The experience with HappyGF has changed how I think about local AI.&lt;/p&gt;

&lt;p&gt;Invoices contain commercially sensitive information, including supplier identities, properties, amounts, and business correspondence. Running open-weight models locally means that information doesn't have to leave the business's own hardware for AI inference.&lt;/p&gt;

&lt;p&gt;But local execution comes with costs of its own: memory, processing power, model loading, and maintenance. On modest hardware, those costs can make a perfectly functional application unpleasant to use.&lt;/p&gt;

&lt;p&gt;Hosted inference offers a different balance. OpenRouter provides controls over prompt logging, provider data collection, and zero-data-retention routing. Those protections are useful, but remote inference still requires sending information to an external provider, whose data-handling policies matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open-weight AI gives us a choice; it doesn't mean local inference is always the best choice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For HappyGF, the practical benefit of open innovation is the ability to experiment with smaller, specialized models, run inference locally when confidentiality requires it, and choose hosted alternatives when convenience matters more.&lt;/p&gt;

&lt;p&gt;Tev1 is a good example. A small decision model can handle certain questions without invoking a larger generative model. And because both the application and TPF are open source, the surrounding workflows and business rules remain inspectable and adaptable.&lt;/p&gt;

&lt;p&gt;The goal isn't to eliminate every external dependency. It's to avoid making any particular inference provider or model an architectural requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  My First User
&lt;/h2&gt;

&lt;p&gt;My girlfriend has been using HappyGF for her actual accounts payable work.&lt;/p&gt;

&lt;p&gt;She's responsible for ensuring that invoices reach the accountant in time for the weekly payment run, and the application was built around the problems she encountered doing that.&lt;/p&gt;

&lt;p&gt;One recent incident illustrates its value particularly well: a contractor submitted an invoice twice. HappyGF identified the duplicate, avoiding another round of manual checking and reducing the risk of processing the same invoice again.&lt;/p&gt;

&lt;p&gt;Her experience has driven the application's development, including decisions about which integrations are worth keeping and whether local inference is practical on the hardware she already owns.&lt;/p&gt;

&lt;p&gt;She hasn't paid me for the application, but she uses it for real work. I'm interested in discovering whether other managers and accounts payable teams face similar problems and would find an open-source alternative useful.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>tpf</category>
      <category>ai</category>
    </item>
    <item>
      <title>Touch grass, and touch glass on a padel court</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Sun, 11 Oct 2026 11:52:24 +0000</pubDate>
      <link>https://dev.to/mbarcia/touch-grass-and-touch-glass-on-a-padel-court-22cn</link>
      <guid>https://dev.to/mbarcia/touch-grass-and-touch-glass-on-a-padel-court-22cn</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Arranging a padel match can be surprisingly tedious. You need four players of roughly similar ability, available at the same time, preferably with compatible expectations. In practice, this means checking club apps, messaging WhatsApp groups, negotiating times, and chasing people for confirmation.&lt;/p&gt;

&lt;p&gt;I wondered whether personal AI agents could handle some of that coordination for us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PadelPot&lt;/strong&gt; is an experiment where four AI agents negotiate a doubles match on behalf of their owners. Each agent knows its player's preferences, can discuss possible arrangements with other agents, and asks its owner when a compromise or commitment requires approval.&lt;/p&gt;

&lt;p&gt;The agents don't exchange complete player profiles. They negotiate using limited information, with privacy and commitment rules enforced by the application rather than left to the language model.&lt;/p&gt;

&lt;p&gt;The idea behind &lt;em&gt;Touch Grass&lt;/em&gt; is straightforward: less time arranging matches, more time playing them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/lz8k7HHAQJc" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The demo follows four fictional players—Alba, Nico, Luz, and Teo—using a WhatsApp-style chat interface. Their agents negotiate a Thursday evening match, resolve a disagreement about the starting time, and obtain approval from all four players.&lt;/p&gt;

&lt;p&gt;The conversations use actual Gemma inference rather than scripted responses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjt63xo1pl587xsr6w48z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjt63xo1pl587xsr6w48z.jpg" alt="Padelpot demo" width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/The-Pipeline-Framework/padelpot" rel="noopener noreferrer"&gt;https://github.com/The-Pipeline-Framework/padelpot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application is open source and includes setup instructions, synthetic player profiles, automated tests, and reproducible demonstration scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;PadelPot is a Java application built using &lt;a href="https://pipelineframework.org/" rel="noopener noreferrer"&gt;The Pipeline Framework (TPF)&lt;/a&gt;, an open-source framework I've been developing for distributed applications.&lt;/p&gt;

&lt;p&gt;It uses Google's open-weight &lt;strong&gt;Gemma&lt;/strong&gt; models for interviewing players and negotiating between agents. I tested the application using Gemma through Ollama, running locally. It also supports inference through OpenRouter.&lt;/p&gt;

&lt;p&gt;TPF provides the typed pipelines, agentic execution, persistence, and asynchronous human interactions. The application handles the matchmaking rules, privacy policies, and final approvals.&lt;/p&gt;

&lt;p&gt;One interesting test sends 30 concurrent approval attempts to the same match. Despite the competing requests, the application never confirms more than four players.&lt;/p&gt;

&lt;p&gt;The first working implementation took a little over an hour using an AI-assisted development workflow, although it builds on TPF infrastructure developed over several years.&lt;/p&gt;

&lt;p&gt;This is a working demonstration with synthetic users, not a production matchmaking service. Real WhatsApp integration, court bookings, and independent hosting of personal agents remain outside its scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;The interesting part of PadelPot isn't simply generating text with an LLM. It's allowing several independently acting agents to negotiate while keeping their behavior constrained by ordinary, testable application rules.&lt;/p&gt;

&lt;p&gt;Open-weight models such as Gemma make it possible to experiment with that behavior locally, inspect the results, change inference providers, and run integration tests without depending exclusively on a proprietary model API.&lt;/p&gt;

&lt;p&gt;TPF is also open source, so the execution model and application architecture can be inspected, tested, and extended.&lt;/p&gt;

&lt;p&gt;For an experiment involving personal information and autonomous agents, that openness matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>mlhacks</category>
      <category>tpf</category>
    </item>
    <item>
      <title>cross-repo testing anyone?</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Tue, 29 Sep 2026 16:37:17 +0000</pubDate>
      <link>https://dev.to/mbarcia/cross-repo-testing-anyone-3oen</link>
      <guid>https://dev.to/mbarcia/cross-repo-testing-anyone-3oen</guid>
      <description>&lt;p&gt;Anyone on my network doing automated testing across multiple repositories / microservices? Curious to know how you are doing, I might have a well-defined product I'd like to build and would love some feedback.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>automation</category>
      <category>microservices</category>
      <category>testing</category>
    </item>
    <item>
      <title>On Jev and Athletics</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Fri, 25 Sep 2026 12:42:47 +0000</pubDate>
      <link>https://dev.to/mbarcia/on-ai-and-athletics-2ghf</link>
      <guid>https://dev.to/mbarcia/on-ai-and-athletics-2ghf</guid>
      <description>&lt;p&gt;I think using AI every day has given us a slightly misleading idea of how easy automation is becoming.&lt;/p&gt;

&lt;p&gt;Models have improved incredibly quickly. Give an AI a browser, some skills and a bit of context and it can do impressive things.&lt;/p&gt;

&lt;p&gt;So it’s easy to think: surely automating the whole process is next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I’m not so sure.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ve been running 100 metres with 30” hurdles — and still hitting a few — and now we’re talking about running 400 metres hurdles at the Olympics.&lt;/p&gt;

&lt;p&gt;A skill that works while you’re watching is very different from something that has to work hundreds of times on its own.&lt;/p&gt;

&lt;p&gt;Small problems multiply. A slow AI call repeated ten times becomes a slow process. Something that’s reliable 98% of the time doesn’t look nearly as good after twenty steps. Websites change, logins expire, bot protection gets tougher. And giving an AI access to everything it might need brings its own obvious problems.&lt;/p&gt;

&lt;p&gt;This is one reason I’ve decided to integrate Jev into The Pipeline Framework.&lt;/p&gt;

&lt;p&gt;Jev doesn’t try to solve all of that. It does something much narrower: make small decisions over supplied data very quickly and very cheaply.&lt;/p&gt;

&lt;p&gt;And that compounds beautifully.&lt;/p&gt;

&lt;p&gt;Data leads to a small decision, which produces more data, which informs another decision, and eventually the software does something.&lt;/p&gt;

&lt;p&gt;That’s much more interesting to me than asking one enormous model to figure out the whole process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big types
&lt;/h2&gt;

&lt;p&gt;Here’s the lovely coincidence I only noticed after integrating Jev.&lt;/p&gt;

&lt;p&gt;The company behind it is called TypeSafe.&lt;/p&gt;

&lt;p&gt;And strong typing is also one of the ideas at the heart of The Pipeline Framework (as is the case with many programming languages).&lt;/p&gt;

&lt;p&gt;That’s not just a naming coincidence: Jev doesn’t return some prose and hope the application interprets it correctly. You give it a defined set of possible decisions and get a structured result back.&lt;/p&gt;

&lt;p&gt;TPF takes the same idea further through the rest of the application: typed data goes into steps, typed data comes out, and those types connect AI decisions, ordinary code, human input and real-world actions.&lt;/p&gt;

&lt;p&gt;Jev makes the decision faster and cheaper.&lt;/p&gt;

&lt;p&gt;TPF makes the process around the decision something you can actually build software on.&lt;/p&gt;

</description>
      <category>jev</category>
      <category>tpf</category>
      <category>automation</category>
      <category>typesafe</category>
    </item>
    <item>
      <title>It took me 18 hours to add Jev</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Wed, 23 Sep 2026 17:29:21 +0000</pubDate>
      <link>https://dev.to/mbarcia/it-took-me-18-hours-to-add-jev-lk7</link>
      <guid>https://dev.to/mbarcia/it-took-me-18-hours-to-add-jev-lk7</guid>
      <description>&lt;p&gt;It took me 18 months to build The Pipeline Framework.&lt;/p&gt;

&lt;p&gt;18 days to turn it into an AI operating system.&lt;/p&gt;

&lt;p&gt;18 hours to add an entirely new kind of AI.&lt;/p&gt;

&lt;p&gt;TypeSafe released Jev only days ago: a System One model that doesn’t generate language. It makes fast, bounded, probabilistic decisions.&lt;/p&gt;

&lt;p&gt;TPF had been built around functional pipelines, "Functional Core, Imperative Shell", reactiveness, scalability, then generative LLMs, RAG, tools, agent loops, MCP, human interaction, durable effects...&lt;/p&gt;

&lt;p&gt;So how much architecture would a fundamentally different model require? Turns out: almost none. So Jev became another Query provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;invoice-judgment-model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;decision.query.jev&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;typesafe/jev-1.13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added a provider-neutral decision protocol:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DecisionRequest → DecisionResult&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;with bounded Choice, Noul and Score questions, then plugged Jev underneath it.&lt;/p&gt;

&lt;p&gt;A real Java application was using it the same day — despite Jev not yet having an official Java SDK.&lt;/p&gt;

&lt;p&gt;And I think that is the milestone I’m happiest about: not that TPF supports the latest AI model, but that it didn’t particularly care that it was new.&lt;/p&gt;

&lt;p&gt;An LLM is a Query. RAG retrieval is a Query. A database lookup is, you guessed it, also a Query. So now a System One probabilistic decision is a Query, as it should.&lt;/p&gt;

&lt;p&gt;Different computational models. Different latency profiles. Different semantics at the provider level. Same application architecture.&lt;/p&gt;

&lt;p&gt;The first 18 months were spent finding the abstractions.&lt;/p&gt;

&lt;p&gt;The next 18 days exploited them.&lt;/p&gt;

&lt;p&gt;The next 18 hours barely disturbed them.&lt;/p&gt;

&lt;p&gt;That’s the compounding return of solid architecture.&lt;/p&gt;

</description>
      <category>jev</category>
      <category>quarkus</category>
      <category>java</category>
      <category>tpf</category>
    </item>
    <item>
      <title>LLMs Generate. Jev Decides. Software Should Know the Difference</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Tue, 22 Sep 2026 16:37:18 +0000</pubDate>
      <link>https://dev.to/mbarcia/llms-generate-jev-decides-software-should-know-the-difference-2dek</link>
      <guid>https://dev.to/mbarcia/llms-generate-jev-decides-software-should-know-the-difference-2dek</guid>
      <description>&lt;h2&gt;
  
  
  Bringing TypeSafe's System One model into a real Java application with The Pipeline Framework
&lt;/h2&gt;

&lt;p&gt;For the last few years, we have been solving an extraordinary range of software problems with essentially the same primitive:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;send some context to a large language model and ask it to generate the answer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That has worked relatively well, but it has also encouraged us to turn problems that are not fundamentally generative into generation problems.&lt;/p&gt;

&lt;p&gt;Classification becomes generation.&lt;/p&gt;

&lt;p&gt;Routing becomes generation.&lt;/p&gt;

&lt;p&gt;Selecting one item from a known catalogue becomes generation.&lt;/p&gt;

&lt;p&gt;Determining whether a condition holds becomes, you guessed it: generation.&lt;/p&gt;

&lt;p&gt;And then, because a generative model is free to generate almost anything, we spend an increasing amount of effort constraining it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Return exactly one of these values.&lt;/p&gt;

&lt;p&gt;Do not invent identifiers.&lt;/p&gt;

&lt;p&gt;Return exactly this JSON structure.&lt;/p&gt;

&lt;p&gt;Do not include an explanation.&lt;/p&gt;

&lt;p&gt;Do not wrap the result in another object.&lt;/p&gt;

&lt;p&gt;Never return anything outside the supplied catalogue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Structured output has made this considerably better. But there is still something slightly peculiar about the underlying architecture.&lt;/p&gt;

&lt;p&gt;We are using a machine designed to generate an open-ended sequence of tokens, and then asking it very politely not to be open-ended.&lt;/p&gt;

&lt;p&gt;TypeSafe's Jev presents a fascinating alternative.&lt;/p&gt;

&lt;p&gt;And when we integrated Jev into The Pipeline Framework and then used it in a real invoice-processing application, something became very clear:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;some of the work we were giving to an LLM was never an LLM problem in the first place.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  System One: AI as a decision function
&lt;/h2&gt;

&lt;p&gt;TypeSafe describes Jev as the first of its &lt;strong&gt;System One Models&lt;/strong&gt;: models designed not primarily to generate language, but to make fast, structured decisions that software can consume directly.&lt;/p&gt;

&lt;p&gt;Instead of an open-ended generation operation, the abstraction is closer to a bounded decision function.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    S[State] --&amp;gt; G[Generative model]
    G --&amp;gt; T[Open-ended tokens]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;versus:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    S[State] --&amp;gt; D[Bounded questions]
    D --&amp;gt; J[System One model]
    J --&amp;gt; R[Probabilistic decisions]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The distinction is profound.&lt;/p&gt;

&lt;p&gt;TypeSafe currently exposes three particularly useful decision shapes: &lt;code&gt;Choice&lt;/code&gt;, &lt;code&gt;Noul&lt;/code&gt;, and &lt;code&gt;Score&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Choice&lt;/code&gt; selects from a finite set of alternatives and returns the corresponding probability information.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Noul&lt;/code&gt; evaluates a proposition probabilistically.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Score&lt;/code&gt; evaluates something against an ordered scale.&lt;/p&gt;

&lt;p&gt;Several independent questions can be evaluated against the same state in one request.&lt;/p&gt;

&lt;p&gt;The output is not primarily prose intended for a human reader. It is information intended for &lt;strong&gt;software&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That changes what the model is being asked to do.&lt;/p&gt;

&lt;p&gt;Consider the difference.&lt;/p&gt;

&lt;p&gt;A generative approach says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read this invoice and tell me which property it belongs to. Return exactly one ID from this list and do not invent another one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A bounded decision instead defines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Which property?

Choice:
    PROPERTY_A
    PROPERTY_B
    PROPERTY_C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first case, selecting a valid identifier is a prompt requirement.&lt;/p&gt;

&lt;p&gt;In the second, it is part of the decision domain.&lt;/p&gt;

&lt;p&gt;That is a much stronger contract.&lt;/p&gt;




&lt;h2&gt;
  
  
  We happened to have exactly the right application
&lt;/h2&gt;

&lt;p&gt;At Mokapot Labs we maintain a small application called Invoice Assistant.&lt;/p&gt;

&lt;p&gt;It is built with The Pipeline Framework (TPF), an open-source framework for constructing typed processing applications.&lt;/p&gt;

&lt;p&gt;The application receives an invoice and a property catalogue, extracts invoice information, determines which property the invoice belongs to, optionally performs visual analysis when the supplier cannot be established from text, presents the result for human confirmation, and then performs the required external effects.&lt;/p&gt;

&lt;p&gt;Its pipeline includes ordinary computation, AI inference, branching, a human Await boundary and replay-safe Commands.&lt;/p&gt;

&lt;p&gt;Before Jev, its text-analysis stage looked roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    A[Invoice] --&amp;gt; B[Extract document text]
    B --&amp;gt; C[Gemma 12B]
    C --&amp;gt; C1[Extract supplier/invoice nr/amount]
    C --&amp;gt; C4[Classify supplier evidence]
    C --&amp;gt; C5[Select property]
    C --&amp;gt; C6[Explain recommendation/w note]
    C1 --&amp;gt; D[Route supplier evidence]
    C4 --&amp;gt; D
    C5 --&amp;gt; D
    C6 --&amp;gt; D
    D --&amp;gt;|Sufficient| E[Review]
    D --&amp;gt;|Insufficient| F[Vision model]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This worked.&lt;/p&gt;

&lt;p&gt;It was not disastrously slow. It was not unreliable enough to force a redesign.&lt;/p&gt;

&lt;p&gt;But the LLM call was doing several fundamentally different jobs.&lt;/p&gt;

&lt;p&gt;And our prompt showed it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The old prompt contained the clue
&lt;/h2&gt;

&lt;p&gt;Part of the original prompt said:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Classify supplier evidence with exactly one qualitative
supplierEvidenceStatus:

EXPLICIT_TEXT
STRONG_TEXTUAL_IDENTITY
INSUFFICIENT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another part said:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Select exactly one property ID present in the supplied
catalogue.

Do not invent, rewrite or normalize property IDs.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read those requirements again in the context of a System One model.&lt;/p&gt;

&lt;p&gt;They describe &lt;strong&gt;Choices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We had an LLM generating a result and a prompt instructing it to behave as though the output space were closed.&lt;/p&gt;

&lt;p&gt;But the output space really &lt;em&gt;was&lt;/em&gt; closed.&lt;/p&gt;

&lt;p&gt;For supplier evidence, there were three possible answers.&lt;/p&gt;

&lt;p&gt;For the property recommendation, the possible answers were precisely the properties already supplied to the application.&lt;/p&gt;

&lt;p&gt;The problem was not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Generate a property identifier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Choose one of these properties.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That difference sounds small.&lt;/p&gt;

&lt;p&gt;Architecturally, it is enormous.&lt;/p&gt;




&lt;h2&gt;
  
  
  But not everything was a Choice
&lt;/h2&gt;

&lt;p&gt;This is where the distinction becomes useful rather than ideological.&lt;/p&gt;

&lt;p&gt;The application also needs to determine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supplier      = "Some arbitrary company name"
invoiceNumber = "INV-2026-18473"
totalAmount   = 68.52
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are open-world values.&lt;/p&gt;

&lt;p&gt;The supplier can be a string we have never encountered before.&lt;/p&gt;

&lt;p&gt;The invoice number is arbitrary.&lt;/p&gt;

&lt;p&gt;The amount is arbitrary.&lt;/p&gt;

&lt;p&gt;These are extraction problems, and our existing generative LLM remains well suited to them.&lt;/p&gt;

&lt;p&gt;So we did &lt;strong&gt;not&lt;/strong&gt; replace the LLM with Jev.&lt;/p&gt;

&lt;p&gt;We split the problem according to its semantics.&lt;/p&gt;

&lt;p&gt;The result became:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    A[Invoice] --&amp;gt; B[Extract document text]
    B --&amp;gt; C["Generative LLM&amp;lt;br/&amp;gt;Gemma"]
    C --&amp;gt; C1[Supplier]
    C --&amp;gt; C2[Invoice number]
    C --&amp;gt; C3[Total amount]

    C1 --&amp;gt; D[Prepare DecisionRequest]
    C2 --&amp;gt; D
    C3 --&amp;gt; D

    D --&amp;gt; J["Jev&amp;lt;br/&amp;gt;System One"]
    J --&amp;gt; J1["Supplier evidence&amp;lt;br/&amp;gt;Choice"]
    J --&amp;gt; J2["Property&amp;lt;br/&amp;gt;Choice"]

    J1 --&amp;gt; P[Probabilistic judgments]
    J2 --&amp;gt; P

    P --&amp;gt; R[Deterministic application policy]
    R --&amp;gt;|Sufficient evidence| H[Review]
    R --&amp;gt;|Insufficient evidence| V["Existing vision model&amp;lt;br/&amp;gt;VLM"]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The generative model generates.&lt;/p&gt;

&lt;p&gt;The decision model decides.&lt;/p&gt;

&lt;p&gt;The application governs what happens next.&lt;/p&gt;

&lt;p&gt;That separation turned out to be more important than simply changing model providers.&lt;/p&gt;




&lt;h2&gt;
  
  
  The LLM prompt got dramatically smaller
&lt;/h2&gt;

&lt;p&gt;The revised generative step now has a much narrower job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Extract only the supplier, invoice number and total amount
from the invoice evidence.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, perhaps more revealingly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do not classify supplier evidence,
select a property,
explain a choice,
generate a note...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM is no longer responsible for everything that happens to involve semantic understanding.&lt;/p&gt;

&lt;p&gt;It is responsible for the part of the problem that genuinely requires open-ended extraction.&lt;/p&gt;

&lt;p&gt;That is an important architectural lesson.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Uses AI" is not a sufficient reason for two operations to belong to the same model call.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Their semantic shapes matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  The System One decision is ordinary Java
&lt;/h2&gt;

&lt;p&gt;There was another complication.&lt;/p&gt;

&lt;p&gt;TypeSafe currently publishes official Python and JavaScript/TypeScript SDKs, but not an official Java SDK.&lt;/p&gt;

&lt;p&gt;Invoice Assistant is a Java application.&lt;/p&gt;

&lt;p&gt;We could have waited.&lt;/p&gt;

&lt;p&gt;We could have introduced Python into the application.&lt;/p&gt;

&lt;p&gt;We could have written a thin application-specific HTTP client.&lt;/p&gt;

&lt;p&gt;Instead, this became an opportunity to establish something more reusable in The Pipeline Framework:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a provider-neutral Java protocol for bounded AI decisions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application constructs an ordinary &lt;code&gt;DecisionRequest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For supplier evidence, it declares:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DecisionQuestion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"supplierEvidence"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;DecisionQuestionType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CHOICE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Judge only the strength of textual evidence identifying the invoice supplier."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DecisionCriterion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"EXPLICIT_TEXT"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"The issuer or supplier is directly labelled or named."&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DecisionCriterion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"STRONG_TEXTUAL_IDENTITY"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"Several consistent textual identity cues identify the issuer."&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DecisionCriterion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"INSUFFICIENT"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"Text is absent, generic, conflicting, or ambiguous."&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The property decision is constructed dynamically from the application's actual property catalogue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DecisionCriterion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"; "&lt;/span&gt;
                &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canonicalAddress&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"; aliases: "&lt;/span&gt;
                &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;aliases&lt;/span&gt;&lt;span class="o"&gt;()))));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DecisionQuestion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"property"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;DecisionQuestionType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CHOICE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Select the supplied property best supported by the invoice evidence."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of my favourite consequences of the change.&lt;/p&gt;

&lt;p&gt;Previously we told the LLM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do not invent property IDs.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the set of possible property IDs &lt;strong&gt;is the decision&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The safety property moved from prose into structure.&lt;/p&gt;




&lt;h2&gt;
  
  
  One state, multiple judgments
&lt;/h2&gt;

&lt;p&gt;The application constructs a state containing the information Jev actually needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extractedFacts
invoiceText
originalFilename
properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and submits both questions together.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    S["Decision state&amp;lt;br/&amp;gt;extractedFacts&amp;lt;br/&amp;gt;invoiceText&amp;lt;br/&amp;gt;originalFilename&amp;lt;br/&amp;gt;properties"]
    S --&amp;gt; R[DecisionRequest]
    R --&amp;gt; Q1["supplierEvidence&amp;lt;br/&amp;gt;Choice"]
    R --&amp;gt; Q2["property&amp;lt;br/&amp;gt;Choice"]
    Q1 --&amp;gt; J[Jev]
    Q2 --&amp;gt; J
    J --&amp;gt; A1["Supplier evidence judgment&amp;lt;br/&amp;gt;choice + probabilities"]
    J --&amp;gt; A2["Property judgment&amp;lt;br/&amp;gt;choice + probabilities"]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;That maps naturally onto the System One model.&lt;/p&gt;

&lt;p&gt;The application is not conducting an agent conversation with the model.&lt;/p&gt;

&lt;p&gt;It is not asking one question, parsing the answer, constructing another prompt and asking another question.&lt;/p&gt;

&lt;p&gt;It describes the state and the bounded judgments it requires.&lt;/p&gt;

&lt;p&gt;The model evaluates them and returns structured results.&lt;/p&gt;

&lt;p&gt;That is a much more application-shaped interaction.&lt;/p&gt;




&lt;h2&gt;
  
  
  The model judges. Software governs.
&lt;/h2&gt;

&lt;p&gt;This may be the most important architectural property of the whole integration.&lt;/p&gt;

&lt;p&gt;Jev does &lt;strong&gt;not&lt;/strong&gt; decide whether the pipeline should execute visual analysis.&lt;/p&gt;

&lt;p&gt;It does not decide whether the application should ask a human.&lt;/p&gt;

&lt;p&gt;It does not execute another capability.&lt;/p&gt;

&lt;p&gt;It doesn't become the workflow engine.&lt;/p&gt;

&lt;p&gt;It returns judgments.&lt;/p&gt;

&lt;p&gt;The application then applies policy.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    J[Jev] --&amp;gt; P["Probabilistic judgments"]
    P --&amp;gt; A["Deterministic application policy"]
    A --&amp;gt;|Text evidence accepted| R[Review]
    A --&amp;gt;|More evidence required| V[Vision analysis]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This boundary matters.&lt;/p&gt;

&lt;p&gt;A probabilistic model is excellent at answering questions such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which supplied property is most strongly supported by this evidence?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It should not automatically acquire authority over:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What should the business process do next?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are different concerns.&lt;/p&gt;

&lt;p&gt;TPF makes that distinction very natural.&lt;/p&gt;




&lt;h2&gt;
  
  
  This is where The Pipeline Framework gets interesting
&lt;/h2&gt;

&lt;p&gt;At first glance, integrating a new AI model might sound like a framework feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind: jev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We deliberately did not do that.&lt;/p&gt;

&lt;p&gt;Jev is not a new kind of pipeline operation.&lt;/p&gt;

&lt;p&gt;From TPF's perspective, Jev observes something the pipeline does not currently know.&lt;/p&gt;

&lt;p&gt;That makes it a &lt;strong&gt;Query&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;TPF's semantic rule is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;known execution-local data   → carry it
fresh external observation   → Query
external side effect         → Command
deferred external completion → Await
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whether the external observation came from PostgreSQL, an HTTP API, an LLM or a System One decision model does not fundamentally change that semantic boundary.&lt;/p&gt;

&lt;p&gt;So the pipeline contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Judge Invoice&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;query&lt;/span&gt;
  &lt;span class="na"&gt;cardinality&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ONE_TO_ONE&lt;/span&gt;
  &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InvoiceJudgmentRequest&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InvoiceJudgmentResult&lt;/span&gt;
  &lt;span class="na"&gt;using&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invoice-judgment-model&lt;/span&gt;
  &lt;span class="na"&gt;operation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;decide&lt;/span&gt;
  &lt;span class="na"&gt;operationVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the provider binding is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;invoice-judgment-model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;decision.query.jev&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;typesafe/jev-1.13&lt;/span&gt;
    &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openrouter-primary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is all the pipeline needs to know.&lt;/p&gt;

&lt;p&gt;There is no Jev step kind.&lt;/p&gt;

&lt;p&gt;There is no System One workflow engine.&lt;/p&gt;

&lt;p&gt;There is no Jev-specific branch operator.&lt;/p&gt;

&lt;p&gt;There is simply another typed external observation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Provider-neutral protocol, provider-specific implementation
&lt;/h2&gt;

&lt;p&gt;This distinction is crucial for avoiding framework lock-in.&lt;/p&gt;

&lt;p&gt;The application does not model its domain using Jev's Python SDK classes.&lt;/p&gt;

&lt;p&gt;Its canonical pipeline types refer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;tpf.decision.DecisionRequest&amp;gt;
&amp;lt;tpf.decision.DecisionResult&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application code constructs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;DecisionRequest&lt;/span&gt;
&lt;span class="nc"&gt;DecisionQuestion&lt;/span&gt;
&lt;span class="nc"&gt;DecisionCriterion&lt;/span&gt;
&lt;span class="nc"&gt;DecisionQuestionType&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provider happens to be &lt;code&gt;decision.query.jev&lt;/code&gt; today.&lt;/p&gt;

&lt;p&gt;The conceptual layering is therefore:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    A[Application domain]
    A --&amp;gt; P["TPF bounded-decision protocol&amp;lt;br/&amp;gt;DecisionRequest / DecisionResult"]
    P --&amp;gt; Q["TPF Query&amp;lt;br/&amp;gt;decide / v1"]
    Q --&amp;gt; X[Provider adapter]
    X --&amp;gt; J[Jev]
    X -. future .-&amp;gt; O[Another bounded-decision engine]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This is substantially different from writing an unofficial Java clone of TypeSafe's SDK.&lt;/p&gt;

&lt;p&gt;TPF is defining the capability the application needs.&lt;/p&gt;

&lt;p&gt;Jev is implementing it.&lt;/p&gt;

&lt;p&gt;That leaves the application architecture independent of one vendor's client library.&lt;/p&gt;




&lt;h2&gt;
  
  
  Java gets a native System One path in the process
&lt;/h2&gt;

&lt;p&gt;This has an interesting practical consequence.&lt;/p&gt;

&lt;p&gt;TypeSafe's official SDKs currently target Python and JavaScript/TypeScript.&lt;/p&gt;

&lt;p&gt;TPF applications can nevertheless use Jev from Java through ordinary typed application code.&lt;/p&gt;

&lt;p&gt;There is no requirement for a Python sidecar.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    J[Java application] --&amp;gt; DR[DecisionRequest]
    DR --&amp;gt; Q[TPF Query]
    Q --&amp;gt; A[decision.query.jev]
    A --&amp;gt; V[Jev]
    V --&amp;gt; RS[DecisionResult]
    RS --&amp;gt; J&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Nor does application code need to manually construct vendor HTTP payloads.&lt;/p&gt;

&lt;p&gt;And because the Java-facing contract is provider-neutral, this integration is useful beyond Jev itself.&lt;/p&gt;

&lt;p&gt;It establishes bounded probabilistic decisions as an application capability in the Java ecosystem rather than merely exposing one vendor endpoint.&lt;/p&gt;




&lt;h2&gt;
  
  
  The output contract became better too
&lt;/h2&gt;

&lt;p&gt;The old property recommendation contained:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;propertyId
explanation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new result contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;propertyId
confidence
probabilities[]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supplier evidence similarly carries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;status
confidence
probabilities[]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This represents a significant change in what the application expects from AI.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    subgraph Before
        A1[AI] --&amp;gt; A2[Answer]
        A1 --&amp;gt; A3[Prose explanation]
    end

    subgraph After
        B1[AI] --&amp;gt; B2[Judgment]
        B1 --&amp;gt; B3[Confidence]
        B1 --&amp;gt; B4[Probability distribution]
    end&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;We had originally added explanations partly as a crutch while introducing the first real LLM Query into the application.&lt;/p&gt;

&lt;p&gt;But prose explanation and model uncertainty are not the same thing.&lt;/p&gt;

&lt;p&gt;A convincing explanation does not necessarily mean a model is confident.&lt;/p&gt;

&lt;p&gt;A terse answer does not necessarily mean it is uncertain.&lt;/p&gt;

&lt;p&gt;For application decisions, explicit probabilistic information is often much more useful.&lt;/p&gt;

&lt;p&gt;The application can inspect it.&lt;/p&gt;

&lt;p&gt;Policy can act on it.&lt;/p&gt;

&lt;p&gt;Telemetry can record it.&lt;/p&gt;

&lt;p&gt;Humans can see uncertainty where useful.&lt;/p&gt;

&lt;p&gt;And future policy changes do not require rewriting a prompt merely to change what confidence means operationally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dead generative work disappeared
&lt;/h2&gt;

&lt;p&gt;The refactoring also exposed functionality that no longer justified its existence.&lt;/p&gt;

&lt;p&gt;The old model generated a short mnemonic note.&lt;/p&gt;

&lt;p&gt;In practice, it was not used.&lt;/p&gt;

&lt;p&gt;So it disappeared.&lt;/p&gt;

&lt;p&gt;The recommendation explanation had largely existed to make early LLM behaviour inspectable.&lt;/p&gt;

&lt;p&gt;It disappeared too.&lt;/p&gt;

&lt;p&gt;This is another benefit of decomposing model responsibilities.&lt;/p&gt;

&lt;p&gt;Large prompts have a tendency to accumulate requirements because adding another sentence feels cheap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;While you're there, also generate...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But inference responsibilities then become coupled together.&lt;/p&gt;

&lt;p&gt;Once the application explicitly separates extraction, decision, policy and presentation, each output has to justify why it exists.&lt;/p&gt;

&lt;p&gt;That is healthy architecture, AI or otherwise.&lt;/p&gt;




&lt;h2&gt;
  
  
  TPF's Functional Core / Imperative Shell model survives AI
&lt;/h2&gt;

&lt;p&gt;One of the recurring problems in agentic systems is that the model gradually absorbs application architecture.&lt;/p&gt;

&lt;p&gt;The model decides what to call.&lt;/p&gt;

&lt;p&gt;The model decides whether to retry.&lt;/p&gt;

&lt;p&gt;The model decides what state matters.&lt;/p&gt;

&lt;p&gt;The model decides when the workflow is finished.&lt;/p&gt;

&lt;p&gt;Eventually the "application" becomes a prompt wrapped around a tool registry.&lt;/p&gt;

&lt;p&gt;TPF deliberately takes another direction.&lt;/p&gt;

&lt;p&gt;The pipeline owns composition.&lt;/p&gt;

&lt;p&gt;Canonical types own application contracts.&lt;/p&gt;

&lt;p&gt;Queries own fresh observations.&lt;/p&gt;

&lt;p&gt;Commands own external effects and, optionally, deferred completion.&lt;/p&gt;

&lt;p&gt;Ordinary application functions own deterministic business policy.&lt;/p&gt;

&lt;p&gt;AI fits inside those boundaries rather than replacing them.&lt;/p&gt;

&lt;p&gt;Invoice Assistant demonstrates that particularly well.&lt;/p&gt;

&lt;p&gt;The model can judge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supplierEvidence =
    STRONG_TEXTUAL_IDENTITY

confidence =
    0.x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but ordinary application code determines what that means for the workflow.&lt;/p&gt;

&lt;p&gt;Likewise, Jev may select a property, but it does not archive the invoice.&lt;/p&gt;

&lt;p&gt;Archiving is an external effect and therefore remains a TPF Command.&lt;/p&gt;

&lt;p&gt;Human property confirmation does not become an agent loop waiting in memory; that, remains an Await boundary.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    P[Typed TPF pipeline]

    P --&amp;gt; Q[Query]
    P --&amp;gt; C[Command (and await)]

    Q --&amp;gt; O[Fresh observation]
    C --&amp;gt; E[External effect]

    O --&amp;gt; L[Generative LLM]
    O --&amp;gt; J[System One / Jev]
    O --&amp;gt; X[Database / API / other provider]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;AI becomes part of software architecture rather than a replacement for it&lt;/p&gt;

</description>
      <category>ai</category>
      <category>jev</category>
      <category>llm</category>
      <category>java</category>
    </item>
    <item>
      <title>One does not simply @Inject in TPF</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Thu, 03 Sep 2026 22:50:05 +0000</pubDate>
      <link>https://dev.to/mbarcia/stop-inject-lm5</link>
      <guid>https://dev.to/mbarcia/stop-inject-lm5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frwr7nhe160aopa3scx5w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frwr7nhe160aopa3scx5w.jpg" alt="One does not simply @Inject in TPF" width="651" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I remember IntelliJ IDEA constantly nudging me away from field injection and toward constructor parameters. Funny how relevant that feels now. The principle was sound: make dependencies explicit. &lt;br&gt;
A pipeline should say what it needs, where it comes from, and how it flows—without invisible framework magic: TPF applies that instinct to the whole application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pipelineframework.org" rel="noopener noreferrer"&gt;https://pipelineframework.org&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tpf</category>
      <category>springboot</category>
      <category>java</category>
      <category>quarkus</category>
    </item>
    <item>
      <title>Where the business actually lives</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Thu, 09 Jul 2026 18:04:01 +0000</pubDate>
      <link>https://dev.to/mbarcia/where-is-the-business-actually-3h72</link>
      <guid>https://dev.to/mbarcia/where-is-the-business-actually-3h72</guid>
      <description>&lt;p&gt;Read the previous episode here:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mbarcia/data-fails-first-3mj3" class="crayons-story__hidden-navigation-link"&gt;Data fails first&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mbarcia" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3186852%2Fc12e3db2-bbe9-47ea-86d4-bfad00f15c5d.JPG" alt="mbarcia profile" class="crayons-avatar__image" width="800" height="1422"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mbarcia" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Mariano Barcia
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Mariano Barcia
                
                
              
              &lt;div id="story-author-preview-content-3718510" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mbarcia" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3186852%2Fc12e3db2-bbe9-47ea-86d4-bfad00f15c5d.JPG" class="crayons-avatar__image" alt="" width="800" height="1422"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Mariano Barcia&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mbarcia/data-fails-first-3mj3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 21&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mbarcia/data-fails-first-3mj3" id="article-link-3718510"&gt;
          Data fails first
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tpf"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tpf&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/java"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;java&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/quarkus"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;quarkus&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/datascience"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;datascience&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/mbarcia/data-fails-first-3mj3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;Software has a strange way of rewarding patience.&lt;/p&gt;

&lt;p&gt;When Marta first introduced TPF into the project, some of her colleagues quietly wondered if the pipeline would become just another obstacle everyone would have to avoid. A few months later, those worries faded. The framework became background noise, the business continued to develop, and people only discussed the architecture when they really needed to.&lt;/p&gt;

&lt;p&gt;Marta thought that was probably a good sign.&lt;/p&gt;

&lt;p&gt;In the meantime, the application had evolved. A second developer joined the team, another carrier integrated, customer support got a small dashboard to check failed orders, and finance requested a daily reconciliation process. None of these changes altered the application's core function. They simply made it more useful.&lt;/p&gt;

&lt;p&gt;Looking back, Marta realized this was exactly the evolution she had hoped for. The pipeline lengthened in some areas, new operators appeared, the generated contracts changed with the business, yet the application felt reassuringly familiar. Reading the pipeline from top to bottom still felt a lot like reading a business process. The architecture remained mostly hidden.&lt;/p&gt;

&lt;p&gt;At least, that’s what she thought.&lt;/p&gt;

&lt;p&gt;Daniel spent most of the previous week adding support for another shipping provider. The implementation went smoothly, but during the code review, he hesitated over a change that seemed harmless at first.&lt;/p&gt;

&lt;p&gt;“I changed the pipeline here,” he said, pointing at the screen, “but I’m not sure the business has changed.”&lt;/p&gt;

&lt;p&gt;Marta leaned in.&lt;/p&gt;

&lt;p&gt;The modification was exactly what she expected. One integration replaced another. The tests passed. The contracts still matched. It was technically sound.&lt;/p&gt;

&lt;p&gt;“What’s bothering you?”&lt;/p&gt;

&lt;p&gt;Daniel took a moment before he replied.&lt;/p&gt;

&lt;p&gt;“I’m not sure yet.”&lt;/p&gt;

&lt;p&gt;He closed the pull request without merging it.&lt;/p&gt;

&lt;p&gt;Later that afternoon, Marta found herself at the coffee machine with Elena. Elena had a knack for listening just enough to ask the right question.&lt;/p&gt;

&lt;p&gt;“You look like you’re debugging something that isn’t broken,” Elena said.&lt;/p&gt;

&lt;p&gt;Marta smiled. “Daniel changed a pipeline step. Everything works. But he thinks the business didn’t change.”&lt;/p&gt;

&lt;p&gt;“And you think?”&lt;/p&gt;

&lt;p&gt;“I think he’s right. I just don’t know why.”&lt;/p&gt;

&lt;p&gt;Elena leaned against the counter. “Walk me through it.”&lt;/p&gt;

&lt;p&gt;Marta hesitated for a moment but then began.&lt;/p&gt;

&lt;p&gt;“Orders come in. We validate them. We reserve inventory. We authorize payment. Then we hand things off to the warehouse.”&lt;/p&gt;

&lt;p&gt;“Sounds like a business,” Elena said.&lt;/p&gt;

&lt;p&gt;“It does. But in between, there are steps that don’t feel like that. We wait for a payment provider. We publish messages. We react to callbacks.”&lt;/p&gt;

&lt;p&gt;Elena nodded slowly. “So?”&lt;/p&gt;

&lt;p&gt;“If I read the pipeline as ‘this is how our business works’, some parts feel... different.”&lt;/p&gt;

&lt;p&gt;Elena picked up her cup. “Different how?”&lt;/p&gt;

&lt;p&gt;Marta thought for a moment. “If we stopped validating orders, the business wouldn’t exist. The same goes for inventory or payment decisions.”&lt;/p&gt;

&lt;p&gt;“What about the other parts?”&lt;/p&gt;

&lt;p&gt;“If we changed how orders arrive, or how the warehouse gets notified, the business wouldn’t describe itself any differently.”&lt;/p&gt;

&lt;p&gt;Elena smiled. “So some steps are the business. Others are just how the business talks to the world.”&lt;/p&gt;

&lt;p&gt;Marta blinked. “Yes. Exactly.”&lt;/p&gt;

&lt;p&gt;They stood there for a moment.&lt;/p&gt;

&lt;p&gt;“So what will you do about it?” Elena asked.&lt;/p&gt;

&lt;p&gt;Marta shrugged lightly. “Nothing dramatic. Just… stop pretending they’re the same thing.”&lt;/p&gt;

&lt;p&gt;Elena laughed. “That’s usually a good start.”&lt;/p&gt;

&lt;p&gt;Back at her desk, Marta reopened the pipeline and read it again, this time thinking of Elena’s words; some steps showed decisions the business cared about, and others showed conversations the application needed to have.&lt;/p&gt;

&lt;p&gt;They were all necessary, but they were not the same.&lt;/p&gt;

&lt;p&gt;She leaned back, thinking how right had Daniel been to hesitate and point out the new code hadn’t changed the business, and revealed where the business actually was.&lt;/p&gt;

</description>
      <category>tpf</category>
      <category>fcis</category>
      <category>springboot</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Data fails first</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Thu, 21 May 2026 14:56:57 +0000</pubDate>
      <link>https://dev.to/mbarcia/data-fails-first-3mj3</link>
      <guid>https://dev.to/mbarcia/data-fails-first-3mj3</guid>
      <description>&lt;p&gt;The strange thing was that the first real scaling problems had nothing to do with scale. Or at least, scale as in "infrastructure scale".&lt;/p&gt;

&lt;p&gt;The application was still relatively small. Traffic was growing, yes, but nothing dramatic. CPUs were healthy, latency was acceptable, deployments remained pleasantly uneventful. From the outside, the system still looked exactly like what it technically was: a single Quarkus application running as a monolith, with pipeline steps invoking one another directly inside the same process.&lt;/p&gt;

&lt;p&gt;And yet developers had started speaking about it differently.&lt;/p&gt;

&lt;p&gt;Not formally. Nobody walked into a meeting and announced that “the architecture had changed.” It emerged indirectly, through the kind of comments engineers make when systems begin slipping away from them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Be careful changing that field.”&lt;/li&gt;
&lt;li&gt;“I think another step depends on this.”&lt;/li&gt;
&lt;li&gt;“We should probably keep the old format for compatibility.”&lt;/li&gt;
&lt;li&gt;“I’m not entirely sure who consumes this anymore.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The incidents themselves were subtle enough to avoid triggering panic. Customer support found two apparently identical shipments taking different routing paths. Finance noticed that premium customers occasionally missed SLA prioritization. A new carrier integration introduced a field named &lt;code&gt;region&lt;/code&gt;, while another team added &lt;code&gt;shipping_region&lt;/code&gt;, and for several months both quietly coexisted because somewhere in the middle of the pipeline a mapper handled the ambiguity without anybody realizing it.&lt;/p&gt;

&lt;p&gt;Nothing crashed.&lt;/p&gt;

&lt;p&gt;That was precisely the problem.&lt;/p&gt;

&lt;p&gt;The failures were no longer technical failures. They were semantic failures. The system continued running while different parts of the application slowly stopped agreeing on what the data actually meant.&lt;/p&gt;

&lt;p&gt;Marta recognized the smell immediately because she had seen it before in event-driven and serverless systems: payloads beginning life as wonderfully flexible JSON blobs and gradually hardening into undocumented distributed contracts. Except this time, it was happening entirely inside a monolith.&lt;/p&gt;

&lt;p&gt;That realization bothered her more than any infrastructure issue they had faced so far because it exposed something most engineers rarely think about when they talk about distributed systems.&lt;/p&gt;

&lt;p&gt;When people hear “distributed systems,” they usually imagine the visible mechanics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;remote calls&lt;/li&gt;
&lt;li&gt;retries&lt;/li&gt;
&lt;li&gt;eventual consistency&lt;/li&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;concurrency&lt;/li&gt;
&lt;li&gt;partitions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But those are often second-order effects. The deeper problem appears much earlier, when independently evolving parts of a system begin sharing meaning imperfectly.&lt;/p&gt;

&lt;p&gt;Two teams interpreting the same field differently. A payload surviving longer than the assumptions under which it was created. Producers and consumers changing independently without realizing the semantic contract between them has drifted.&lt;/p&gt;

&lt;p&gt;That is already a distributed systems problem, even if everything still runs inside one JVM.&lt;/p&gt;

&lt;p&gt;And that was the moment Marta realized something important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Distribution is not a deployment problem. It starts as a data problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The architecture diagrams had not changed yet, but the organizational reality already had. Different teams owned different stages of the pipeline. External integrations introduced their own semantics. Some transformations were deterministic and easy to reason about; others depended on databases, carrier APIs, fraud services, and infrastructure outside the team’s control. The application might still have been physically centralized, but conceptually it had already become a collection of independently evolving boundaries.&lt;/p&gt;

&lt;p&gt;That was where TPF started becoming much more than a convenient orchestration framework.&lt;/p&gt;

&lt;p&gt;The team was not using it as a generic workflow interpreter where loosely defined tasks execute dynamically at runtime. What TPF increasingly provided was something much closer to a typed application pipeline compiler: a system capable of understanding the boundaries between stages well enough to generate contracts, validate transformations, wire transports, expose endpoints, and fail builds when parts of the pipeline drifted out of alignment.&lt;/p&gt;

&lt;p&gt;The distinction mattered enormously.&lt;/p&gt;

&lt;p&gt;The pipeline steps themselves remained ordinary application code. Developers wrote Quarkus services, plain Java methods, some reactive Mutiny handlers where concurrency justified the complexity, some blocking implementations where simplicity mattered more than theoretical throughput. Nobody had to abandon the normal ergonomics of application development to “enter the workflow engine.”&lt;/p&gt;

&lt;p&gt;But the boundaries between those steps became explicit.&lt;/p&gt;

&lt;p&gt;Instead of passing anonymous maps through the system and hoping conventions would survive organizational growth, stages now declared typed inputs and outputs, mapper rules, cardinality expectations, operator contracts, and transport compatibility in ways the compiler could actually verify.&lt;/p&gt;

&lt;p&gt;The effect on development was immediate and surprisingly human. Refactoring became less frightening. Teams stopped relying on tribal knowledge to understand dependencies. A mapper mismatch became a compilation error instead of a production incident discovered three weeks later through telemetry dashboards and apologetic Slack messages.&lt;/p&gt;

&lt;p&gt;Peace of mind was alas, restored, once all the data contracts between steps were formalised, and the architecture stopped evolving accidentally.&lt;/p&gt;

</description>
      <category>tpf</category>
      <category>java</category>
      <category>quarkus</category>
      <category>datascience</category>
    </item>
    <item>
      <title>The Lift and Shift</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Thu, 07 May 2026 18:12:31 +0000</pubDate>
      <link>https://dev.to/mbarcia/the-lift-n-shift-378b</link>
      <guid>https://dev.to/mbarcia/the-lift-n-shift-378b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the continuation of &lt;a href="https://dev.to/mbarcia/the-script-that-refused-to-stay-small-1mod"&gt;"The script that refused to stay small"&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The conversation had already been happening for months: three data centers, rising costs, aging hardware, and a growing sense that the whole setup was one incident away from becoming a liability.&lt;/p&gt;

&lt;p&gt;The decision came quickly after the "kalima" event: everything had to move.&lt;/p&gt;

&lt;p&gt;What followed was not elegant, as the platform team scrambled to pull off a lift &amp;amp; shift to the cloud:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hypervisor VMs mapped 1:1 into cloud instances&lt;/li&gt;
&lt;li&gt;network rules replicated (and occasionally guessed)&lt;/li&gt;
&lt;li&gt;storage reattached, sometimes awkwardly&lt;/li&gt;
&lt;li&gt;timelines optimistic, then revised, then ignored&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most applications... just came along for the ride whilst Marta watched all of this unfold.&lt;/p&gt;

&lt;p&gt;Her service was, technically, just another VM in the inventory. It could have been copied over, like everything else, but the lift and shift was rushed and was accumulating tech debt almost by definition. So she made a different call.&lt;/p&gt;

&lt;p&gt;Instead of following the 1:1 VM migration path, she opted into an early container platform the company had been experimenting with—something not yet standard, slightly under-documented, but good enough.&lt;/p&gt;

&lt;p&gt;Not because she was trying to be innovative, but because her system made it easy.&lt;/p&gt;




&lt;p&gt;Containerizing the application turned out to be almost trivial.&lt;/p&gt;

&lt;p&gt;Quarkus already produced a lean runtime, with the pipeline living inside a single process with well-defined boundaries. There were no hidden dependencies on the host, no fragile startup scripts, no tight coupling to the underlying machine.&lt;/p&gt;

&lt;p&gt;Marta wrote a Dockerfile, wired a couple of environment variables, and that was… mostly it.&lt;/p&gt;

&lt;p&gt;The hardest part wasn’t the application, but everything around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;getting the right network access&lt;/li&gt;
&lt;li&gt;aligning with security policies&lt;/li&gt;
&lt;li&gt;making sure it could talk to the same external systems as before&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So while most systems were being translated from one VM to another, Marta’s was quietly being repackaged.&lt;/p&gt;

&lt;p&gt;And once it ran, something became clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It was still a monolith&lt;/li&gt;
&lt;li&gt;Steps still called each other directly, in-process&lt;/li&gt;
&lt;li&gt;The pipeline still lived entirely inside a single runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only the execution environment had changed.&lt;/p&gt;




&lt;p&gt;That was the first quiet lesson &lt;a href="https://pipelineframework.org" rel="noopener noreferrer"&gt;The Pipeline Framework&lt;/a&gt; taught the team: you can move where something runs without changing how it behaves.&lt;/p&gt;

&lt;p&gt;A few weeks later, someone asked Marta how long her migration had taken; she hesitated (because the honest answer sounded wrong: “About a day. Maybe two, if you count the networking issues.”&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Photo credit: Javier Mediavilla E, CC BY-SA 2.5 &lt;a href="https://creativecommons.org/licenses/by-sa/2.5" rel="noopener noreferrer"&gt;https://creativecommons.org/licenses/by-sa/2.5&lt;/a&gt;, via Wikimedia Commons&lt;/em&gt;&lt;/p&gt;

</description>
      <category>quarkus</category>
      <category>java</category>
      <category>tpf</category>
      <category>serverless</category>
    </item>
    <item>
      <title>The Script That Refused to Stay Small</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Thu, 09 Apr 2026 21:54:41 +0000</pubDate>
      <link>https://dev.to/mbarcia/the-script-that-refused-to-stay-small-1mod</link>
      <guid>https://dev.to/mbarcia/the-script-that-refused-to-stay-small-1mod</guid>
      <description>&lt;p&gt;It started, as these things often do, with a single process running on a single machine in a server room nobody liked visiting. The system took in shipment requests, enriched them with a few heuristics, and spat out routing hints. Nothing fancy, just enough logic to save operations teams a few hours a day, and Marta built it on her own as a side project.&lt;/p&gt;

&lt;p&gt;Marta wasn’t new to Java, she had spent a few months working in a microservices project in Spring and liked the serverless functional-style thinking: small transformations composed together. She had enough scar-tissue by now having experienced the inevitable issues with Spring and wanted to experiment with Quarkus anyway.&lt;/p&gt;

&lt;p&gt;She picked TPF because, on top of featuring a canvas UI to design the pipeline, she got the complete app's scaffolding as a pure Quarkus project. She could keep developing on her IDE as usual, only with the addition of the Quarkus environment plugin. And, she got to use Dev Services which she also wanted to try.&lt;/p&gt;

&lt;p&gt;Her choices for the script were deliberately boring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a JVM runtime (a single process) with&lt;/li&gt;
&lt;li&gt;no high availability&lt;/li&gt;
&lt;li&gt;a traditional direct method invocation between the orchestrator and the pipeline steps&lt;/li&gt;
&lt;li&gt;no DB, just basic HTML responses to human queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each step in the pipeline was just a function. Input came in as loosely structured key/value data. No rigid schema, no upfront modeling, no SQL persistence.&lt;/p&gt;

&lt;p&gt;She didn’t yet have to think about&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;execution tracking or audits&lt;/li&gt;
&lt;li&gt;fan-out/fan-in logic&lt;/li&gt;
&lt;li&gt;retry semantics&lt;/li&gt;
&lt;li&gt;error handling&lt;/li&gt;
&lt;li&gt;availability&lt;/li&gt;
&lt;li&gt;high throughput&lt;/li&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;integrations with 3rd parties&lt;/li&gt;
&lt;li&gt;monitoring&lt;/li&gt;
&lt;li&gt;security&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And because she had started using AI-assisted coding tools, even the tests came almost for free, as TPF’s step isolation made it trivial to generate meaningful unit tests for each transformation.&lt;br&gt;
It was fast. It was understandable. It worked and, crucially, it already had shape—even if nobody called it that yet.&lt;/p&gt;

&lt;p&gt;But during one summer's day, a sandstorm from the Sahara impacted  Valencia and caused temperatures to rise (a phenomenon called kalima). The A/C unit in the server room failed and, by the next morning morning, alerts were firing, CPUs were throttling, and someone mentioned, only half jokingly, the possibility of actual fire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0tquvjm4qn8haoc57at.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0tquvjm4qn8haoc57at.webp" alt="Dust cloud over Gandia, Valencia" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>quarkus</category>
      <category>java</category>
      <category>tpf</category>
      <category>unittest</category>
    </item>
    <item>
      <title>Architectural mobility for stronger software</title>
      <dc:creator>Mariano Barcia</dc:creator>
      <pubDate>Tue, 07 Apr 2026 19:37:36 +0000</pubDate>
      <link>https://dev.to/mbarcia/architectural-mobility-for-stronger-software-2nh4</link>
      <guid>https://dev.to/mbarcia/architectural-mobility-for-stronger-software-2nh4</guid>
      <description>&lt;p&gt;There’s a concept in sports science that’s easy to overlook because it sounds so basic: “mobility”. Mobility is defined as “the ability of a joint to move actively through its full, functional range of motion with control, stability, and strength“.&lt;/p&gt;

&lt;p&gt;If you look at a simplified “athlete performance” pyramid, the foundation isn’t power or strength; it’s mobility. Everything else builds on top of that, but we spend most of our time discussing the upper layers and very little attention is paid to what sits at the foundation of the pyramid. Take away mobility, and the strength will falter.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       / - \
      /     \
     / Power \    Athlete Performance Pyramid
    /_________\
   / Strength  \  
  /_____________\
 /   Mobility    \ 
/_________________\
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, the reasons why mobility is so important are many and complex, but basically have to do with how the nervous system is able to recruit muscle fibres, whilst at the same time staying healthy (ie. by doing “reciprocal inhibition”). &lt;/p&gt;

&lt;p&gt;Putting aside the inherent complexity of the muscles in the human body, I think software systems behave in a similar way, and we spend most of our time discussing the upper layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scalability&lt;/li&gt;
&lt;li&gt;throughput&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;whilst paying very little attention to what sits underneath all of that.&lt;/p&gt;

&lt;p&gt;Most software systems miss something fundamental: they cannot change shape without breaking themselves.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You move from containers to functions → everything rewrites&lt;/li&gt;
&lt;li&gt;You switch from REST to gRPC → contracts ripple through the system&lt;/li&gt;
&lt;li&gt;You change how remote work is executed → business logic gets entangled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system might be “strong” in its current form, but it lacks mobility. It’s rarely stated explicitly, and runtime, transport, and protocol are treated as the same decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You deploy to containers → you expose REST → you serialise JSON.&lt;/li&gt;
&lt;li&gt;Or you go serverless → you wire HTTP → you pass payloads around.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing looks wrong and in fact, it feels coherent, but still:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your execution model has dictated your transport&lt;/li&gt;
&lt;li&gt;your transport has dictated your protocol&lt;/li&gt;
&lt;li&gt;and all three together have dictated your system shape&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This affects “architectural mobility” because&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You cannot change where things run without rewriting how they communicate&lt;/li&gt;
&lt;li&gt;You cannot change how they communicate without rewriting what they mean&lt;/li&gt;
&lt;li&gt;You cannot evolve protocols without locking yourself into a runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That mobility is what allows your business logic to evolve regardless of any external infrastructure decision, and will allow you to make these deliberate choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;do your workloads belong in containers?&lt;/li&gt;
&lt;li&gt;do your workloads belong in serverless functions?&lt;/li&gt;
&lt;li&gt;do they benefit from gRPC, or REST?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;a href="https://pipelineframework.org" rel="noopener noreferrer"&gt;The Pipeline Framework&lt;/a&gt;, architectural mobility is enabled by decoupling the transport from the execution platform from the runtime topology, like so: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                     Transport
               (LOCAL / REST / gRPC / Proto-HTTP)
                           ↑
                           │
                           │
                           │
                           │
                           │
                           ●───────────────→ Execution Platform
                          /                (COMPUTE / FUNCTION)
                         /
                        /
                       /
                      ↓
             Runtime Topology
  (Monolith / Pipeline / Modular)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Photo credit: &lt;a href="https://unsplash.com/es/@weareambitious" rel="noopener noreferrer"&gt;https://unsplash.com/es/@weareambitious&lt;/a&gt;&lt;/p&gt;

</description>
      <category>quarkus</category>
      <category>java</category>
      <category>software</category>
      <category>tpf</category>
    </item>
  </channel>
</rss>
