Nugget 19: Distill Before You Distribute
Problem
While building WORKS Commons, I found myself looking at Docker, Kubernetes, microservices, and Domain-Driven Design (DDD). After spending years maintaining a large enterprise monolith, I wondered whether my architecture was falling behind modern practices.
The temptation was obvious:
"I have BackgroundServices. Maybe they should become microservices."
At first glance, the idea sounded reasonable. Modern systems often advertise:
Kubernetes
Microservices
Event-Driven Architecture
Distributed Systems
However, something felt forced.
Observation
Most of WORKS Commons consists of tightly related business workflows:
Job Applications
↓
Interview
↓
Evaluation
↓
Training
These components share concepts, state, and business rules. Separating them simply because container technology exists would increase complexity without providing meaningful benefits.
The real issue was not deployment.
The real issue was architectural distillation.
The project currently contains:
Presentation
JobBank (Blazor)
Data
JobBank.Data
Contracts
JobBank.Management.DTO
ETL
JobBank.EtlConsole
Tests
WORKSCommons.Tests
What is missing is an explicit Application Layer containing business modules and their contracts.
Lesson
A common mistake, in my view, is jumping directly from:
Monolith
to:
Microservices without first creating clear internal boundaries.A healthier evolution is:
Monolith
↓
Modular Monolith
↓
Distributed Services (if justified)
The objective is not to create services.
The objective is to identify business boundaries.
Examples might include:
Interviewing
Training
Job Applications
Analytics
Employment Feed Processing
These boundaries can exist entirely within a single process.
The Litmus Test
Before extracting a service, ask:
What do I gain?
Specifically:
Independent scaling?
Independent deployment?
Separate ownership?
Different availability requirements?
Different storage requirements?
If the answer is:
"Nothing, but it feels modern."
Leave it in the monolith.
When a Service Begins to Make Sense
WORKS Commons revealed one area that may eventually justify extraction.
The automatic rejection workflow:
Find stale applications
↓
Automatically reject
↓
Generate analysis request
↓
LLM processing
↓
Persist signals
Unlike user-facing features, this workload is:
Asynchronous
Batch-oriented
Potentially expensive
Rate-limited by LLM APIs
Potentially scalable
This is the first component in the system that exhibits characteristics commonly associated with independent services.
However, even here the next step is not Kubernetes.
The next step is separation of responsibilities.
For example:
Rejection Processing
↓
Analysis Request Queue
↓
LLM Analysis Worker
All running inside the same application.
Only when scale, deployment cadence, or operational requirements demand it should service extraction be considered.
Takeaway
Docker and Kubernetes are deployment technologies.
DDD is a modeling discipline.
Neither should drive architecture.
The domain should.
If a system needs clearer boundaries, create modules.
If a module later needs independent scaling, deployment, or ownership, it may naturally evolve into a service.
Distill first. Distribute later.
That sequence is architecture.
The reverse is often fashion.
Growth exposes deficits.

Comments
Post a Comment