The Dilemma Every Architect Faces
How do we build systems that are cohesive enough to be understandable and decoupled enough to evolve independently?
On one side: the monolith — initial simplicity that becomes a nightmare.
On the other: microservices — flexibility that can become operational complexity.
What if there was a mental framework that balanced these forces? There is. And it comes from an unexpected place: a 1967 philosophy book.
Arthur Koestler and the Concept of Holon
In 1967, Hungarian-British philosopher Arthur Koestler published "The Ghost in the Machine". Frustrated with simplistic dichotomies, he coined a new term: holon.
Etymology
- holos (Greek): "whole", "entire"
- suffix -on: connotes "particle" (like proton, neutron)
Holon = an entity that is simultaneously a complete WHOLE and a PART of something larger.
The Fundamental Duality
"Every holon has two tendencies: an integrative tendency to function as part of a larger whole, and a self-assertive tendency to preserve its individual autonomy."
— Arthur Koestler
Koestler called this the "Janus effect" — like the Roman god with two faces. Every holon looks simultaneously inward (its integrity) and outward (the larger system).
Holons in Nature
Your body is a perfect holarchy:
ORGANISM
└── ORGAN (heart)
└── TISSUE (cardiac muscle)
└── CELL
└── ORGANELLE
Each level is:
- Autonomous: functions on its own
- Integrated: contributes to the whole
When this balance breaks? Cancer — cells that maintain autonomy but lose integration.
The Problem with Traditional Architectures
Poorly Structured Monolith
Components are just parts — no real autonomy:
- Can't test in isolation
- Can't deploy independently
- Failure propagates everywhere
Suppressed the self-assertive tendency.
Poorly Implemented Microservices
Dozens of services with synchronous HTTP forming a "distributed monolith":
- Chained synchronous calls
- One failure brings down all
- Complexity without benefit
Nominal autonomy, chaotic integration.
Self-Contained Systems: Holonomy in Practice
German company INNOQ formalized the concept of Self-Contained Systems (SCS).
Characteristics
| Principle | Description |
|---|---|
| Autonomous | Complete web application |
| Vertical Slice | UI + logic + own data |
| No sync in request/response | Doesn't call other SCS synchronously |
| Single team | One team per SCS |
The Golden Rule
Other SCS should not be accessed synchronously within the request/response cycle.
If you need data from another SCS → have a local copy updated via events.
SCS vs Microservices: An Honest Comparison
What is NOT a difference
❌ "SCS uses async, microservices uses sync"
Wrong. Modern microservices use Kafka, RabbitMQ, event-driven architecture.
The real differences
| Aspect | SCS | Microservices |
|---|---|---|
| Quantity | 5-25 | 50-500+ |
| UI | Mandatory | Optional |
| Granularity | Business domain | More granular |
| Sync in request | Prohibited | Allowed |
Anatomy of a Software Holon
┌─────────────────────────────────────────────┐
│ HOLON: Orders │
├─────────────────────────────────────────────┤
│ PUBLIC INTERFACE │
│ • REST/GraphQL API │
│ • Published events (Kafka) │
│ • Consumed events │
├─────────────────────────────────────────────┤
│ DOMAIN LOGIC │
│ • Business rules │
│ • Workflows/Sagas │
├─────────────────────────────────────────────┤
│ PERSISTENCE │
│ • Own database │
│ • Replicas of external data │
├─────────────────────────────────────────────┤
│ SELF-REGULATION │
│ • Health checks │
│ • Circuit breakers │
│ • Metrics │
└─────────────────────────────────────────────┘
The Dependency Rule
// ❌ WRONG
import { InventoryService } from '../inventory';
// ✅ CORRECT
await eventBus.publish({
type: 'OrderCreated',
payload: order
});
Holons don't import other holons directly.
Challenges of Asynchronous Communication
1. Event Ordering
Sent: [A, B, C]
Received: [A, C, B] 😱
Solution: Kafka guarantees order per partition.
2. Duplication (at-least-once)
if (await alreadyProcessed(event.id)) return;
await process(event);
await markAsProcessed(event.id);
3. Eventual Consistency
Accept it as reality. UI shows "processing..." when needed.
4. Distributed Debugging
Correlation ID in all logs + Jaeger/Zipkin.
When to Use (and When Not)
✅ Use when:
- Multiple distinct domains
- Teams need independence
- High availability is critical
- Differentiated scale per domain
❌ Avoid when:
- Small system, single team
- MVP or proof of concept
- Strong consistency is required
- No experience with distributed systems
Evolution Path
Modular Monolith
↓
Separate schemas
↓
Introduce messaging
↓
Complete Holonomic System
Evolve when the pain justifies it, not before.
Conclusion
Holonomy isn't a silver bullet. It's a mental framework.
What Koestler taught us: resilient systems maintain balance between being a whole and being a part.
Monoliths, microservices, SCS — all can work. Wisdom lies in choosing right for the context.
References
- Koestler, Arthur. "The Ghost in the Machine" (1967)
- SCS Architecture
- Microservices.io - Saga Pattern
- Apache Kafka
"The whole is more than the sum of its parts, but the parts are more than fragments of the whole."
Liked it? Leave a ❤️ and share with anyone facing architecture decisions!
Want to discuss? Comment below 👇
Top comments (0)