Complexity Is Interaction, Not Just Size

LESSON

Complexity and Systems Thinking

001 30 min intermediate

Complexity Is Interaction, Not Just Size

By the end of this lesson, you will be able to...

  • Distinguish a complicated system from a complex system.

  • Classify a system behavior by looking for interaction, feedback, and partial local knowledge.

  • Explain why a locally reasonable rule can produce a surprising system-level result.

Idea in one sentence: A system is complex when the important behavior comes from interaction among parts, not just from the number of parts.

Core Insight

A service starts responding slowly.

Each client has a reasonable rule:

If the request times out, try again.

That rule is sensible for one client. A retry can hide a short network hiccup. It can turn a temporary failure into a successful request.

Now make the situation bigger.

Ten thousand clients hit the same slow dependency. Each client sees only its own timeout. Each client retries. The dependency now receives original requests plus retry requests. Its queue grows. Responses get slower. More clients time out. More clients retry.

No client is trying to cause an outage. No component contains a line of code named create_retry_storm(). Still, the whole system can move into a new pattern: rising queues, repeated work, synchronized pressure, and failure spreading through dependencies.

This is the first move in systems thinking:

Do not ask only, "How many parts are there?"
Ask, "What do the parts do to each other?"

A large system can be merely complicated. A smaller system can be complex. The difference is not size by itself. The difference is whether interaction changes the behavior you need to explain.

The Confusion This Concept Solves

It is tempting to use "complex" as a stronger word for "big" or "hard."

A jet engine has many parts. A tax form has many rules. A codebase may have thousands of files. These things can be complicated. They may require expertise, careful documentation, and a lot of patience.

But complicated is not the same as complex.

A complicated system can often be understood by decomposing it:

part A does this
part B does that
part C connects them

If each part behaves as specified, the whole is usually easier to predict.

A complex system resists that move. The parts still matter, but the important behavior appears when parts influence one another over time. The result depends on timing, feedback, connectivity, local information, and changing conditions.

In the retry example, one client retrying is easy to understand. Ten thousand clients retrying against the same slow service is different. The fleet-level behavior is not just "one retry multiplied by ten thousand." The retries change the condition that caused the retries.

That circular influence is the beginning of complexity.

A Small Example

Consider two systems.

System A is a report generator:

1. Read yesterday's sales records.
2. Group them by region.
3. Calculate totals.
4. Write a PDF.

This system may be complicated. The schema may be messy. The PDF library may be painful. But if the input data is fixed and the code is deterministic, the same run should produce the same report.

System B is a queue-backed checkout service:

1. Clients submit checkout requests.
2. Requests wait in a queue.
3. Workers process requests.
4. Clients retry when they wait too long.
5. Autoscaling adds workers when the queue grows.

This system may have fewer visible pieces than the report generator. Still, it is more complex. Why?

Because the pieces influence each other while the system runs.

The behavior is not only inside the clients, the queue, or the workers. The behavior is in the loop between them.

The Precise Meaning

Plain meaning:

A complex system is one where the pattern you care about comes from interaction among parts.

In our scenario:

The outage is not explained by one bad client or one broken worker. It is explained by many clients, one shared dependency, queueing delay, retry timing, and feedback between them.

Technical name:

This is a complex system. A complex system has interacting parts whose combined behavior can be hard to predict from the parts in isolation.

This does not mean the system is magical. It does not mean "random." It means that the explanation lives at the interaction level.

A useful test is:

If I inspect each part alone, do I still understand the behavior?

If yes, the system may be complicated but not strongly complex.

If no, the system is likely complex. You need to inspect the interaction pattern.

Worked Classification: The Retry Storm

Let us classify the retry storm step by step.

Step What one part sees What the whole system does
1 A client sends a request. Normal load reaches the service.
2 The service is slow, so the client times out. A queue is already building somewhere.
3 The client retries because retrying often helps. Extra requests increase total load.
4 Many clients make the same local decision. Queue depth rises faster than workers can drain it.
5 Slower responses create more timeouts. The retry rule feeds the condition that triggered it.
6 Each client still looks reasonable in isolation. The fleet has entered a positive feedback pattern.

The input is a slowdown.

The transition is local retry behavior.

The intermediate state is a growing queue with more duplicate work.

The output is a system-level pattern: overload reinforced by retries.

The naive failure contrast is important. If we only ask, "Is retrying a failed request reasonable?" the answer is often yes. If we ask, "What happens when every client retries the same slow dependency at the same time?" the answer changes.

So far, we have seen that complexity is not measured by counting components. It is detected by following influence. The client changes load. Load changes latency. Latency changes client behavior. Client behavior changes load again.

That loop is the lesson.

What This Is Not

Complexity is not the same as messiness.

A messy system may have unclear names, old code, missing documentation, or inconsistent interfaces. That makes work harder, but it is not automatically complexity in the systems-thinking sense.

Complexity is not the same as randomness.

Emergent behavior can look surprising, but it usually has structure. In the retry storm, the pattern is caused by repeated rules and shared constraints. It is not noise.

Complexity is not always bad.

Useful behavior can also emerge from interaction. A gossip protocol spreads cluster membership because each node shares partial information with a few peers. No node needs to know the whole cluster at once. The system-level pattern, eventual spread of information, comes from repeated local exchange.

The question is not "How do we remove all complexity?" Many useful systems cannot remove it. The better question is "Which interactions create the behavior, and what signals show that the interaction is moving toward trouble?"

The trade-off is decomposition versus interaction reasoning. Decomposition makes the parts easier to inspect, but it can hide the loop that actually explains the system-level behavior. Interaction reasoning is slower, but it shows the feedback pattern you must design, observe, or limit.

Common Confusions

Confusion: Many parts means complex

Why it is tempting:

Large systems are hard to hold in memory. It feels natural to call that complexity.

Better model:

Many parts make a system complicated. Interaction among parts makes it complex. A large static checklist can be complicated without much interaction. A small feedback loop can be complex.

Confusion: Local correctness guarantees system correctness

Why it is tempting:

Engineering often tests one component at a time. If every component passes its tests, it feels like the whole should work.

Better model:

Component correctness is necessary, but it is not enough. The retry rule can be correct inside one client and harmful when many clients apply it together under shared load.

Confusion: Emergent behavior is always unpredictable

Why it is tempting:

Emergent behavior is often surprising the first time you see it.

Better model:

Emergent behavior can be studied. You may not predict every event exactly, but you can often identify the local rules, feedback loops, thresholds, and signals that shape the pattern.

Check Your Understanding

Check: A build system has 400 independent steps. Each step reads fixed input files and writes a fixed output. Is this complexity in the systems-thinking sense, or mainly complication?

Think first, then reveal.

Answer: Mainly complication. The system may be large and difficult, but if the steps do not strongly influence one another while running, decomposition explains most of the behavior.

Check: A small chat room has 20 people. One rumor causes anxious messages, anxious messages make the rumor seem more credible, and the increased credibility causes more anxious messages. What makes this complex?

Think first, then reveal.

Answer: The behavior comes from interaction and feedback. Each person reacts to local messages, but the group-level pattern amplifies through repeated influence.

Practice

Classify each situation as mainly complicated, complex, or both. Then explain the interaction pattern if one exists.

  1. A payroll calculator has 120 tax rules, but the same employee record always produces the same paycheck.
  2. A marketplace changes seller ranking based on buyer clicks, and sellers change prices and titles in response to ranking changes.
  3. A deployment script has 40 steps. Step 23 fails if a previous step writes the wrong config file.

A good answer should mention:

Model answer:

The payroll calculator is mainly complicated. It may be hard, but the rules are mostly fixed transformations. The marketplace is complex because buyers, sellers, ranking, and pricing influence one another over time. The deployment script is both: it is complicated because it has many steps, and it has a small interaction dependency because one step changes the conditions for a later step. It becomes more complex if failures cause retries, rollbacks, alerts, or human interventions that change the system while it runs.

Resources

Key Takeaways

NEXT Local Rules and Emergent Behavior