I have been writing software for a long time, and for most of that time the job had a stable shape: someone describes a behaviour, you turn it into lines of code, you ship it, you maintain it. That shape is cracking. Not because models write code faster than I do (they do, and it matters less than people think), but because the unit of work is moving. The interesting systems I see now are not "programs" in the old sense. They are a memory, a stream of things that happened, and a set of workers that react to those things. This post is my opinion on what that means for the next few years, which skills actually pay off right now, and how a small company can use this shift to beat a bigger one.

Why is the future of programming not about writing more code

The cost of producing a line of code is heading towards zero. That is the boring part of the story. The expensive part never was the typing, but It was knowing what the business actually does, keeping that knowledge consistent across a codebase, and finding out what happened when something broke at 3 am. None of those got cheaper because a model can emit a controller in four seconds.

So if code is cheap, what is the scarce thing? In my experience it is two things: structured knowledge about your domain that a machine can read, and a reliable record of what happened in your system. A company that has both can point agents at problems and get useful work out of them. A company that has neither gets a very fast generator of plausible-looking bugs.

That is why I think the architecture of the next decade will not be organised around lines of code at all. It will be organised around three pillars.

What are the three pillars of the future architecture

The picture that keeps showing up, in my own projects and in the ones I review, is the same: a knowledge graph as the brain, an event bus as the nervous system, and agent orchestration as the workforce. Each one is old technology. What is new is that together they replace the thing we used to call "the application".

How does a knowledge graph become the system's memory

A normal relational schema stores facts in tables and hides the relations in join logic that lives in code. That is fine for a human developer who reads the code. It is useless for an agent that has to answer "why did this customer's invoice get a discount" without reading forty service objects.

A knowledge graph makes the relations first-class. The system does not just know that user 42 exists and product 17 exists. It knows that user 42 purchased product 17, that product 17 has the attribute "subscription", and that the "subscription" attribute triggers a pricing rule. The graph is what lets a model understand the context of the whole business instead of one table at a time.

You do not need a graph database to start. In Postgres a single edges table with a recursive query covers a surprising amount of ground:

CREATE TABLE facts (
  subject   text NOT NULL,
  predicate text NOT NULL,
  object    text NOT NULL,
  recorded_at timestamptz NOT NULL DEFAULT now(),
  PRIMARY KEY (subject, predicate, object)
);

-- Everything reachable from a customer within three hops
WITH RECURSIVE context AS (
  SELECT subject, predicate, object, 1 AS depth
  FROM facts
  WHERE subject = 'customer:42'
  UNION ALL
  SELECT f.subject, f.predicate, f.object, c.depth + 1
  FROM facts f
  JOIN context c ON f.subject = c.object
  WHERE c.depth < 3
)
SELECT subject, predicate, object
FROM context
ORDER BY depth;

The facts table is a plain triple store: subject, predicate, object. The recursive part starts from one node and follows every outgoing edge, three hops deep, so the result is the neighbourhood of that customer: their orders, the products in those orders, the attributes of those products, the rules attached to those attributes. That neighbourhood is exactly what you hand to an agent as context. It is small, it is relevant, and it is the same shape for every question, which is a much better deal than dumping a schema and hoping. I know it would be better to use correct archetype like accounting but it's not always possible to do in old-legacy projects.

Why is an event bus the nervous system

The graph tells you what is true. It does not tell you what just happened. For that you need a stream of events: "button clicked", "price changed", "payment failed", "deploy finished". Every component of the system, human-written or agent-driven, can react to those signals the moment they arrive instead of polling a table or waiting for a nightly job.

I have written about events on this blog many times, and the lessons still hold in an agent world. The event needs a stable name, a stable envelope, and metadata that says where it came from. In Ruby that can be as small as this:

# app/events/event.rb
Event = Data.define(:name, :payload, :metadata) do
  def self.build(name, payload, actor:, correlation_id: SecureRandom.uuid)
    new(
      name: name,
      payload: payload,
      metadata: {
        actor: actor,
        correlation_id: correlation_id,
        occurred_at: Time.now.utc
      }
    )
  end
end

# app/events/bus.rb
class Bus
  def initialize
    @handlers = Hash.new { |hash, key| hash[key] = [] }
  end

  def subscribe(name, handler)
    @handlers[name] << handler
  end

  def publish(event)
    EventLog.append(event)
    @handlers[event.name].each { |handler| handler.call(event) }
  end
end

The point of the metadata hash is that the actor field can now be a person, a cron job, or an agent, and every downstream consumer can tell the difference. The correlation_id is what lets you trace a chain of reactions back to the click that started it. The EventLog.append call before dispatch is deliberate: the log is the source of truth, the handlers are just readers of it. If you skip that line you end up with a system that reacts to things and then forgets they happened, which is the worst of both worlds.

If you want the long version of what to put in the envelope and what to keep out of the payload, I covered that in Events in distributed architecture: are you sure you know what you're sending?.

How does agent orchestration replace one big program

Instead of a single application that does everything, the system becomes dozens of specialised processes. One agent handles payments, another handles image generation, another watches the error stream and proposes fixes. Orchestration is the layer that makes them cooperate without chaos: who reacts to what, in which order, and what happens when one of them is wrong.

The trap here is to let the model do the routing. Do not. Routing is deterministic work, and deterministic work belongs in code. The model is for judgment: classify this, draft that, summarise the other. An orchestrator that respects that boundary looks boring, and boring is the goal.

I compared single, sequential and parallel agent setups in AI agents system architecture: possible strategies. The orchestrator above is the sequential variant with an event bus in the middle, and that combination is the one I would pick for anything that touches money.

What matters right now for a developer

This is what I think is worth learning, in the order in which it has paid off for me.

Domain modelling comes first. If you cannot name the entities and relations in your business clearly enough to write them into a triple store, no agent will do it for you. The people who did DDD and event storming for the last decade were, it turns out, preparing training data for their own future systems.

Second is event design: naming, envelopes, idempotency, ordering. It is the same skill as before, only now the consumers are less predictable, so the discipline matters more. A sloppy event that a human consumer tolerated will send an agent off in a wrong direction at scale. If your current setup already has events but every service still needs every other service to be up, read Why your event-driven architecture may actually be a distributed monolith before adding agents to it.

Third is evaluation. Writing a prompt is easy. Knowing whether the output was right, over a thousand runs, with a number attached, is the skill. Treat agent output like you treat a flaky test: measure it, log it, put a threshold on it, and refuse to ship on vibes.

Fourth, and this one is underrated, is owning your data pipeline. Graph plus event log is only a moat if you actually have the data and can read it. Companies that outsourced their event tracking to a marketing tool and their relations to a SaaS CRM are going to find that the interesting context lives in someone else's database.

What matters less than people think: memorising a specific model's quirks, a specific agent framework, or a specific vector database. Those are churning every quarter. The three pillars are not.

How does this architecture beat competing companies

The technical argument only matters if it wins something, so here is the business side.

A big competitor has more engineers, but their knowledge is spread across those engineers' heads and a decade of code that nobody fully reads anymore. A small company that starts with a graph and an event log has its whole business legible to a machine from day one. When a new capability shows up, the small company points an agent at the graph and ships a feature in a week. The big one schedules a discovery phase.

The event log is the second advantage. Every decision an agent makes is a recorded event with a correlation id, which means you can replay a month of history against a new agent version and see how it would have behaved. Your competitor is still arguing about whether the new prompt is better. You have a number. I wrote about that replay mindset in Event sourcing in practice: lessons from the trenches, and it transfers directly.

The third is headcount shape. Dozens of narrow agents supervised by a few engineers who understand the domain beats a large team of generalists who each know one slice. That is what my current projects look like today, not a forecast.

Common mistakes when moving to agents and events

The most common one is starting with the agents. People wire a model to a few tools, get a demo working, and then discover there is no memory and no history to make it reliable. Build the graph and the log first; the agents are the easy part.

The second is letting the model orchestrate. A prompt that says "decide which of these tools to call" is a routing table you cannot read, test, or diff. Keep routing in code and keep judgment in the model.

The third is treating the event log as a queue. If events disappear after consumption, you lose replay, you lose audit, and you lose the ability to retrain or re-evaluate. Append first, dispatch second, keep everything.

The fourth is granting agents direct write access to core tables. Agents emit events; deterministic handlers decide what gets persisted. That single indirection is what lets you turn an agent off at 3 am without corrupting anything.

FAQ

Do I need a graph database for a knowledge graph

No. A Postgres table of triples with recursive queries carries most systems a long way. Move to a dedicated graph store when traversal depth or write volume forces you to, not before.

Is an event bus the same as a message queue

Not for this purpose. A queue delivers a message once and forgets it. What you want here is an append-only log that handlers read from, so the history survives and can be replayed. Kafka, a Postgres table, or an event store all work; the append-first rule is what matters.

Will AI agents replace developers in this architecture

They replace the typing. Somebody still has to model the domain, design the events, set the thresholds, and read the replay numbers. That somebody is the developer, and the job moved up a level rather than disappearing.

How many agents should a system have

As many narrow ones as you have clearly separable responsibilities, and no more. If two agents need each other's internal state to work, they are one agent with a bad boundary.

Happy orchestrating!