Skip to main content

26 posts tagged with "architecture"

View All Tags

The Most Dangerous Code Has a Save Button

· 11 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 20

On a Thursday, someone on the finance-ops team opened the admin panel to update a tax table. A new state rate had taken effect: 7.25%. They found the field, typed 7.25, clicked Save, and moved on to the next row. The system stored tax rates as decimals, so 0.0725 meant seven and a quarter percent. The field took 7.25 at face value. For the next two days, every order shipping to that state was taxed at seven hundred twenty-five percent. The first customer to complain had been charged more tax than the price of the goods.

Nobody deployed anything. No pull request was opened. No test ran. No reviewer looked at it. The most expensive behavior change the business made that quarter went out with less scrutiny than a one-line typo fix in the codebase would have received.

This is not a story about a careless employee. It is a story about a system that decided, somewhere along the way, that this particular kind of behavior change did not count as code, and therefore did not deserve any of the protection we give to code.

Name the Dragon

· 14 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 19

There is a system with four thousand tests; all green. They have been green for months. CI is fast, the team trusts it, deploys go out daily, and nobody is embarrassed to say the platform is well covered. Yet, it just shipped a refund larger than the original charge.

That sounds like a testing failure, and in the shallow sense it is. Somewhere there should have been a test that caught it. Somewhere there should have been a case, an assertion, a fixture, a fake payment, a mocked refund, a regression test with the right numbers in the right columns. But that is not the interesting failure. The interesting failure is that the rule was never a thing the system could point at.

A refund cannot exceed the settled charge. Simple sentence. Obvious sentence. The kind of sentence everyone in the room agrees with as soon as the incident review begins. And yet, before the incident, where did that sentence live? A little of it lived in the refund service. A little of it lived in an admin form. A little of it lived in a database constraint. A little of it lived in the payment gateway integration. A little of it lived in the memory of the person who last fixed the related bug. To test the rule, you had to drive the whole platform from the outside and hope the dragon wandered into view.

What Time Is It?

· 12 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 18

A customer adds a jacket to their cart on Friday night. It is on promotion: 30% off, a weekend sale. They get distracted, come back Monday morning, and check out. What do they pay?

There is a correct answer, a defensible answer, and the answer the code actually gives. In a surprising number of systems those are three different numbers, and the last one was chosen by nobody at all. The code's answer turns on one small decision made deep inside a pricing function: when that function needed to know the time, where did it get it?

Exactly Once Is a Lie

· 11 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 17

You send a command to unlock a door; not a metaphor, an actual lock, on an actual door, opened over the network because a tenant is standing outside it and your service has decided to let them in. The command goes out. Somewhere between your server and the lock a packet is lost — not the command, the acknowledgment. The lock opened. The confirmation never came back. From where your code stands, the operation has no result. The safest-looking move, the one every retry policy in the world will make, is to send the command again.

Whether that second command is harmless or a small disaster was decided long ago, not by the network, but by whoever modeled the operation. And the same question hides inside far more than the state of a lock. Provision a server, and a lost reply means you pay for two. Issue a customer the license they bought, dispatch a shipment, send a notification, publish a post, grant a permission… Every one is the same operation: an effect that leaves your control and cannot be pulled back, reached across a channel that can lose the receipt.

Large Action Models Need Small Action Surfaces

· 13 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 16

A language model can answer a question. An action model can do something about it. That distinction is going to matter more than most commerce platforms are ready for. Whether the term is "agent," "large action model," "task-specific AI," or something else that marketing teams have not finished sanding down yet, the direction is clear enough: software will not merely describe commercial options to buyers, operators, partners, and employees. It will increasingly select actions, call tools, negotiate constraints, and attempt to move workflows forward.

In commerce, "move the workflow forward" is not a harmless phrase. It might mean reserving inventory. It might mean accepting a substitution. It might mean committing an order, issuing a refund, changing a shipping promise, requesting a quote, applying a contract price, cancelling a shipment, or escalating a return. These are not generic software actions. They move money, create obligations, expose data, affect inventory, alter customer trust, and (should) leave evidence behind for someone else to explain later.

The Aggregate Cost of Composition

· 10 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 14

Most engineers don't wake up at 3am thinking about chargebacks, but most commerce operators eventually do. A chargeback has a way of turning a small, messy edge case into an expensive, cross-functional incident. Support gets involved. Finance gets involved. Someone pulls logs. Someone else pulls warehouse records. Payment provider screenshots are taken. A bank is now part of the conversation. Whatever the customer's original question was, it has been upgraded from "help me understand" to "prove it." No matter who wins that proof point, the merchant is stuck with the cost of proof.

That cost is not just the refunded transaction. Often, the expensive part is the work required to reconstruct the story. The customer says they were charged twice. The payment provider shows one authorization, one capture, one retry, and maybe a reversal or refund depending on which screen you are looking at. The order management system says the order was accepted. The warehouse says it shipped. The carrier says it was delivered. The promotion engine says the discount was valid at checkout. The customer's email confirmation preserves a total that was true at the moment it was sent. The ledger preserves a different total after tax, shipping, substitution, split shipment, cancellation, or refund logic had its say. Everyone may be telling the truth, locally, and still no one can answer the customer's question cleanly.

It Was Never about the Money

· 9 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 13

The total comes back as 59.666666666667, and somewhere downstream we must ensure that we don't end up with 59.67ontheinvoiceand59.67 on the invoice and 59.66 in the ledger.

The instinct is to reach for more precision. But precision was the easy part. A drifting penny is a symptom. The disease is poor modeling. "Money is not a number. Money is a number plus everything we forget to carry with it."

Capability Surfaces: A Mediating Architecture for Agent-Native Commerce

· 21 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Abstract

The emergence of autonomous software agents as primary actors in commercial transactions creates a structural integration problem: agents need to interact with thousands of independent merchants, each exposing heterogeneous APIs with incompatible schemas, inconsistent semantics, and varying reliability guarantees. Existing integration patterns — direct REST consumption, EDI, or bespoke connector libraries — scale as O(A × M) where A is the number of agents and M is the number of merchants. We identify this as the agent-merchant integration problem and propose capability surfaces as a mediating architectural pattern that reduces integration complexity to O(A + M).

A capability surface is a semantic contract layer that sits between a merchant's internal microservices and external agents. It exposes deterministic, versioned, discoverable operations with explicit input/output schemas and error semantics, enabling any compliant agent to transact with any compliant merchant without bespoke integration. We formalize the pattern, specify its required properties, and ground the analysis in a concrete three-party scenario (manufacturer, procurement agent, logistics provider) interacting across an open market without pre-built integrations.

We examine the Model Context Protocol (MCP) as a production-validated mechanism for expressing capability surfaces, and the Universal Commerce Protocol (UCP) as an early domain-specific vocabulary layer. We discuss open problems in contract governance, registry trust, and agent identity that the architecture does not yet resolve.

Delegating the Deal: Human Authority, Accountability, and Oversight in Agent-Mediated Commerce

· 22 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Abstract

Autonomous software agents are increasingly executing commercial transactions on behalf of human principals — discovering suppliers, evaluating offers, and placing orders without human involvement at each decision point. This paper examines the human factors dimension of this transition: what changes when humans delegate purchasing authority to agents, how the cooperative structure of commerce changes when one or more parties to a transaction is a software system, and what oversight, accountability, and trust mechanisms are required for agent-mediated commerce to function within organizational contexts.

We analyze a three-party transaction scenario (human principal, procurement agent, manufacturer) to identify the moments of delegation, the accountability gaps that delegation creates, and the design requirements for capability surfaces — the architectural interface layer through which agents interact with merchants — that support rather than undermine human oversight. We argue that the technical architecture of agentic-commerce systems encodes assumptions about human authority that deserve explicit examination, and that CSCW research has important contributions to make in designing systems where automation is a tool of human delegation rather than a replacement for human judgment.

A Protocol Stack for Agent-Native Commerce: MCP, Domain Profiles, and Open Interoperability

· 19 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Abstract

The growth of autonomous software agents as commercial actors — buyers that discover suppliers, evaluate constraints, and execute transactions without human involvement — creates a practical interoperability problem: how should agents and merchants communicate when they have no prior relationship and no bespoke integration? This article presents a protocol stack perspective on the emerging answer: a layered architecture combining the Model Context Protocol (MCP) as a general capability mechanism, commerce-domain profiles as shared vocabularies, and capability registries as discovery infrastructure. We examine the stack's current state, its gaps, and the open engineering problems that the community must resolve to support agentic-commerce at production scale.

Is the FP Juice worth the Squeeze?

· 5 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 11

Adopting functional programming isn't free. It requires training investment, a shift in team culture, and a willingness to tolerate an awkward middle period where the codebase is neither cleanly imperative nor fully functional. So the honest question — the one that belongs in a technology leadership conversation — is whether the benefits actually justify the cost.

This is my attempt at a direct answer, organized around the risk categories that tend to matter most in enterprise commerce organizations.

When MVPs Grow Teeth

· 6 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 10

Bad models are rarely designed by teams on purpose. Most of the time it's the model you get by being pragmatic: shipping an MVP, and then doing the next reasonable thing… repeatedly… for two years.

You start with a product structure that fits a world where you can store something on a shelf, put it in a box, and ship it to a customer. When the business decides to stock other stuff, you add more attributes to accommodate. When the business wants customization — engraving, embroidery, monogramming — and now "the product" has options that change price and lead time, you start sub-typing. When subscriptions, warranties, DRM, and other non-physical entitlements become strategic, you do more of the same. Nothing here is exotic. It's just what happens when the business grows and adapts.

Folding in Traceability

· 4 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 9

In enterprise commerce, totals don't drift because someone forgot algebra. They drift because reality changes: promos expire, eligibility changes when an address arrives, catalog data updates, substitutions happen, and returns unwind prior discounts. When someone asks "why did the total change?" you need more than narration. You need evidence — a trail of facts you can replay and a pure computation that deterministically produces the same result.

That responsibility falls to foldLeft.

Not All Errors are Exceptional

· 6 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 8

Not every "error" in a system represents a defect. Many outcomes that matter to a business are perfectly legitimate: a promotion does not apply, a configuration is incomplete, a shipment cannot be routed to a destination, a request is valid but cannot yet be satisfied. Treating these outcomes as exceptions often obscures their meaning. Exceptions are excellent for broken invariants and infrastructure failures; they are much less effective for representing business decisions that the system should be able to explain, persist, and reason about later.

In Scala, one of the tools commonly used to model these outcomes is Either. There is no shortage of articles explaining how to use Either for error handling, and many of them are worth reading. What those articles sometimes struggle to convey is why this representation changes how systems behave, especially for developers coming from imperative backgrounds. Either can feel abstract until it is attached to a boundary where the distinction between two outcomes actually carries meaning.

Modeling Absence without Ambiguity

· 5 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 7

Most enterprise systems operate under a subtle assumption that proves surprisingly costly: representing absence as a value. In Java and comparable languages, this value is null, appearing everywhere to denote missing, unknown, inapplicable, or forgotten things. Teams eventually stop noticing it, but this familiarity creates problems.

While null wasn't inherently flawed — it solved a genuine constraint in early object-oriented languages — trouble emerged when it began representing multiple distinct concepts simultaneously. In real systems, null might signify that a value doesn't apply, wasn't provided, hasn't loaded yet, a lookup failed, configuration is missing, or upstream errors occurred. All these situations collapse into one representation with no explanation.

Why Pattern Matching Matters

· 6 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 6

By this point in the series, we've spent a lot of time making the mechanics of code disappear. We stopped mutating values because mutable values drift. We stopped depending on external state because it breaks determinism. We stopped writing statements because expressions are clearer, safer, and easier to compose. And, most recently, we stopped writing loops because functional transformations let the business logic stand on its own.

But there is another way imperative languages obscure meaning — and this one is subtler. It happens any time a developer tries to figure out what kind of thing something is before deciding what to do with it.

Beyond the For-Loop: Mastering map, filter, and flatMap

· 5 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 5

Even after developers embrace immutability and pure functions, one imperative construct persists: the for-loop. It remains the last artifact to disappear because it's the first structure we learn. In Java, it feels inevitable as the only intuitive way to examine lists, select relevant data, and produce results.

However, for-loops obscure business logic. Before expressing a domain rule, developers must decide how to iterate, where to accumulate results, when to branch, which state to mutate, and how structures evolve. All of that precedes stating anything meaningful about the business itself.

Thinking in Expressions, Not Statements

· 4 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 4

Developers transitioning from non-functional languages typically acquire functional concepts incrementally — lambdas, immutability, pattern matching, collection operations. While the syntax may appear elegant, the fundamental conceptual breakthrough often comes much later. That breakthrough involves recognizing that thinking in expressions rather than statements represents the true bridge between imperative and functional paradigms.

Imperative programming emphasizes procedural steps with variable mutation. Functional programming reframes the question entirely: "What value are we computing?" This expression-centric approach eliminates entire classes of complexity because there's no timeline of state changes, no mutable accumulators, and no branches requiring variable adjustments. Everything becomes composable values.

Pure Functions: Your First Step Toward Bug-Free Concurrency

· 9 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 3

In Part 2, we explored how mutable state — especially state that someone once believed was a fact — tends to drift over time, and how this drift destabilizes large systems. Immutability is a corrective measure: if something is a fact, preserve it. But immutability addresses only one dimension of stability. The other dimension concerns the way behavior is expressed — whether the logic we rely on actually does what its name claims, or whether it also does several other things we never quite account for.

When developers talk about pure functions, they often recite the textbook definition: same inputs, same outputs, no side effects. It's correct, but it undersells the point. Purity is not an aesthetic choice or an academic curiosity. It is a way of reclaiming control over the semantics of your system. It is how you establish that a piece of business logic actually behaves like business logic, rather than a negotiation with global state, shared caches, volatile time checks, and whichever service instance happens to answer the call.

Immutability by Default: The Foundation of Reliable Systems

· 9 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

Functional Programming Isn't Just for Academics — Part 2

Most introductions to immutability begin with trivial examples. A string is mutated, the result changes, and we are invited to contemplate the danger. But enterprise systems don't fail because someone appended characters to the wrong buffer. They fail because something that was supposed to be a fact — a value that anchored downstream behavior — continued to evolve with the system rather than remaining bound to the moment it was created.

Distributed systems fail when truth drifts. This is why immutability is not a stylistic preference or a functional-programming curiosity. It is the architectural foundation for building systems that behave predictably in a world that does not.

Functional Programming Isn't Just for Academics: Why It Matters for the Systems We Build Now

· 8 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

In 1983 I asked my parents for an Atari for Christmas, instead I got a Commodore 64… Needless to say, I was very disappointed until I discovered how much cooler Wizard of Wor was than Combat. To their credit, my parents thought a computer was a better investment than a video game. I used that C64 through my sophomore year of college until I replaced it with a 486; my first real investment. So, like many in my generation, I cut my teeth on programming languages like BASIC and LOGO without really picking them for any reason. It was just kind of cool, as a kid, to be able to tell a computer what to do and watch it do it. I quickly understood that animating ASCII stick figures was a BASIC problem and digital Spirograph was a job for the LOGO turtle. In college I was using FORTran for math and science and C for everything else knowing that, depending on the task, one was more natural than the other.

An Introduction to Reactive Commerce

· 3 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

If your commerce platform drives critical revenue and the services it provides are difficult to predict in nature or scale — or if optimizing user experience depends on near-real-time responses to changing signals — reactive commerce warrants attention. Reactive commerce orchestrates digital discovery, selling, purchasing, and merchandising while adhering to the Reactive Manifesto's principles.

Headless Commerce: Advice for Goal Hangers

· 5 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

So, you are considering headless commerce and have made your way through the talks, videos, and articles but still have doubts? The very first thing you need to do is understand who you are and what you are trying to do, so you can properly dissect the arguments for or against a headless approach. The headless commerce value proposition is blended across numerous stakeholders: providers, consumers, and end users. This means that there may be perfectly valid arguments for going one way or the other that may not apply to your decision. Knowing what you are looking for will help you discard the noise and concentrate on what matters for you and your organization.

Agility and the Headless Commerce Debate

· 7 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

So, you are considering headless commerce and have made your way through the talks, videos, and articles but still have not decided what to do? The arguments for transitioning to headless commerce are numerous and touch several domains. It is useful to categorize the value proposition by the segments they impact:

  • Providers — Those whose business is the building, delivery, and/or maintenance of digital commerce platforms.
  • Consumers — Those who subscribe to commerce platforms and/or services as a vehicle to grow their core business.
  • Users — Those who are immersed in a digital commerce experience.

The return on investment in headless commerce is different for each group. As agility is perhaps the most often cited benefit of headless commerce, let's use that as an example.

Why Do They Call Them Apartments When They're All Stuck Together?

· 5 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

I'm a big fan of service oriented front-end design and microservice based architectures. If I were building a new service to take to market, I'd most likely go that way. Certainly, I would design it cloud native and my MVP would be API-first… After all, why would I invest the effort of building a slick UI when everyone is so gaga to go headless? But, as a purveyor of digital commerce, would I redeploy my front-end to take advantage of headless design or rearchitect my back-end to leverage all the advantages of a microservice architecture? Probably not.

Modeling Distribution on Tracing Ideals: A Novice's View on COVID-19 Vaccine Management

· 6 min read
Tony Moores
Founder & Principal Consultant, TJM Solutions

I am neither a medical nor healthcare expert but I believe some of our approaches to managing the spread of Corona have lacked sensibility and I am hoping the manner in which forthcoming vaccines are distributed is more soundly aligned to science and logic. I am not talking about whether one should wear a mask or engage in high risk activities or not. Americans, at least, have made up their minds for better or worse.

I live in a community where measures to mitigate the risk of infection are more or less left to the institutions that remain running. I applaud the leaders of our local school district for their balanced approach. They have instituted a a mix of in-person and on-line education and have school nurses, who regularly consult with HHS, in touch with the organizations in which their students participate to institute policy to mitigate risk to at large. For example, a student playing hockey for an organization unaffiliated with the high school contracted Covid. The nurse was was notified. In addition to restricting all teammate of the infected individual to on-line classes for 14 days, requiring a negative test result prior to resuming on-campus activities, the nurse contacted leaders of schools of teammates not of our district, the hockey coaches and team parents to coordinate contact tracing. Rather impressive for the, "Live Free or Die," state, but not without flaws. The exposed student athletes were quarantined because they were potential disease vectors, but what of the other members of their household? Their siblings were not, in turn restricted, leaving parents to decide whether to extend such measures to themselves and other children. Two parents, essential postal workers, sacrificed vacation time for safety's sake, but siblings of other families hunkering down around the same breakfast tables went to school and in some cases, to sports.