Microservice or shared library? A decision framework
Whenever shared logic appears across several products, the question often arrives too early: "Should we extract this as a microservice?"
The more useful question is less flashy:
ImportantWhat specific problem am I trying to solve: reuse, secrets, compute, centralized deployment or organizational isolation?
Decision map
The four goals that get confused
When someone says "microservice", they are often mixing different goals:
| Real goal | Better tool | Microservice? | Practical signal |
|---|---|---|---|
| Reuse logic across products | Shared library | Not as the first answer | Same code, same semantics |
| Protect secrets | Server-side service | Yes | Keys, tokens or private signatures |
| Run heavy compute | Specialized service | Yes | PDF, headless browser, ML, batch jobs |
| Change behavior without updating clients | Versioned API | Sometimes | Many external consumers or teams |
Architecture gets clearer when these goals are separated. A microservice solves secrets, compute and centralized operations well. It does not magically solve reuse.
Quick comparison
Shared library
Use it when logic is pure, portable and needs to run near the consumer.
- Local render.
- Validators.
- Parsers.
- Secret-free transformations.
Microservice
Use it when runtime matters or the client must not see what happens.
- Private keys.
- Deploys.
- Server-side exports.
- Billing, licenses and audit.
Both
Use both when there is a pure core and a server-side case wrapping it.
- Render core.
- Exports API.
- Publishing service.
- Portal previews.
Runtime question
The first question is always where the logic must execute.
| Required runtime | Implication |
|---|---|
| Browser | You cannot protect the code. You can package it better, not hide it. |
| Offline desktop | You need a local library. A service would break offline mode. |
| Server | You can protect secrets and control deploys. |
| Worker or job | You can isolate cost, memory and permissions. |
Warning"Let's make it a microservice to protect the code" is incomplete. If the client needs to execute that logic, the code will still be in the client.
Real case: Markdown rendering in a multi-product platform
The enriched Markdown renderer looked like a microservice candidate because several products used it. Applying the framework:
| Question | Answer | Decision |
|---|---|---|
| Must it run offline in the editor? | Yes | Library |
| Is it pure logic without secrets? | Yes | Library |
| Are there more than three consumers? | Yes | Extract package |
| Is there a server-side case? | Yes, exports and publishing | Service that imports the library |
| Does the service have its own secrets? | Yes, deploys, quotas, third-party credentials | Microservice for exports and publishing |
Result:
Using both library and service is not a contradiction. The contradiction would be turning a pure function into a remote API and breaking offline mode just to call it architecture.
When the service is the answer
There are cases where a shared library is not enough:
| Case | Why it needs a service |
|---|---|
| Deploy to edge or static hosting | The client must not hold deploy tokens |
| License signing | The private key belongs on the server |
| Reliable PDF export | Render engine, fonts and runtime need control |
| Billing | Subscription state is authoritative on the server |
| Audit | Logs must be central, signed and not client-editable |
TipIf you can write a pure function with clear input and output, start with a library. If you need permissions, secrets, authoritative state or infrastructure, start with a service.
Anti-patterns
Signs of a premature microservice
- There is only one real consumer.
- The logic must run offline.
- There are no secrets or heavy compute.
- The API would be a remote call around a pure function.
- The service only exists because it "looks cleaner".
- Latency and deployment cost exceed maintenance savings.
Signs that a required service is hidden inside a library
- The library needs third-party tokens.
- The client could bypass quotas or plans.
- The result must be audited.
- The computation consumes too much memory or CPU for the client.
- Every consumer reimplements permissions, billing or deployment.
Operational rule
Before moving a piece, I write this sentence:
| Template | Good example | Bad example |
|---|---|---|
| "I extract it to X to solve Y in Z runtime" | "I extract it to a service to sign licenses with a private key on the server" | "I extract it as a microservice to protect the code" |
| "I extract it to a library to share Y across Z consumers" | "I extract it to a library to render Markdown the same way in editor, web and dashboard" | "I extract it because it is duplicated twice" |
The rule I keep
Do not choose between microservice and library by fashion. Choose by runtime, secret, compute, number of consumers and contract.
This article is part of my architecture notes. If you are interested in this topic, follow the blog or contact me.