What Is MIC?¶
MIC means Model / Interface / Controller. It is a structure for production services built with Python or Node.js / TypeScript:
- Model: stable representations of data, contracts, and domain rules;
- Interface: inbound and outbound contracts expressed independently from the framework that transports them;
- Controller: thin orchestration that connects Model and Interface to execute one use case.
Think of it as MVC turned around: the HTTP framework is not at the center. Domain behavior stays at the center, while FastAPI, Litestar, Express, Fastify, Hono, NestJS, or Node HTTP become replaceable adapters.
The MIC Contract in One Picture¶
graph TB
A[HTTP client] -->|request| B[Python adapter<br/>FastAPI / Litestar]
A -->|request| C[Node.js adapter<br/>Node HTTP / Express / Fastify / Hono / NestJS]
B --> D[Route contract<br/>HttpRouteSpec / route]
C --> D
D --> E[Controller<br/>handler]
E --> F[Model<br/>domain service]
F --> G[(Service-owned<br/>persistence)]
F --> H[External service<br/>signed client]
E --> I[Canonical<br/>HTTP result]
I --> B
I --> C
B -->|response| A
C -->|response| A
Primitive names follow each language's idioms, but the boundary remains the same: a route contract describes inputs, outputs, and errors; the handler runs domain behavior; the adapter translates the result for the selected framework.
One Contract, Two Idioms¶
| Need | Python | Node.js / TypeScript |
|---|---|---|
| Static or governed contract | StrictSchema, SchemaRegistry |
schema, GovernedSchemaRegistry |
| Permanent or transient failure | DomainError, TransientError |
DomainError, TransientError |
| Framework-neutral route | HttpRouteSpec |
route() |
| Signed service-to-service client | ServiceHttpClient |
ServiceHttpClient |
| Organization-scoped persistence | TenantScopedRelationalStore |
TenantScopedRelationalStore |
| HTTP adapters | FastAPI, Litestar | Node HTTP, Express, Fastify, Hono, NestJS |
| Generator | mic-python cookiecutter |
@mic-struct/create-mic-service |
This correspondence is a shared doctrine, not a hidden compatibility layer. Each implementation remains idiomatic in its language. Services communicate through explicit contracts such as OpenAPI, versioned events, or strictly validated messages.
Three Layers, Three Responsibilities¶
Model¶
Everything that describes what: static or governed schemas, entities, domain errors, invariants, and domain services. This layer knows nothing about HTTP request objects, framework decorators, or global connections.
Contracts reject unknown fields. Errors carry a stable code and state whether retrying is valid. Dependencies are received explicitly.
Interface¶
Everything that describes how the service talks to the outside world: HTTP routes, authentication, service clients, events, message queues, and operator commands.
A MIC interface publishes enough metadata to be verified and documented. For HTTP, the same contract drives the runtime adapter and the OpenAPI document.
Controller¶
Everything that describes when: HTTP handlers, consumers, workers, and periodic tasks. A controller receives validated data, calls the domain service, and returns a canonical result. It orchestrates; it does not own domain rules.
What MIC Is Not¶
- Not a new HTTP framework. Frameworks stay in place; MIC uses them as adapters.
- Not Clean Architecture or Hexagonal Architecture in disguise. The domain-infrastructure boundary is familiar, without mandatory layers of ceremonial classes.
- Not a dependency-injection container. Assembly remains explicit, readable, and testable.
- Not an ORM. Database schemas, migrations, indexes, and engine-specific queries remain service responsibilities.
- Not an abstraction that erases Python and TypeScript. MIC preserves their types, tools, and conventions instead of inventing a smaller common denominator.
Who Is It For?¶
- Teams writing multiple Python services, TypeScript services, or both.
- Teams that want the same baseline guarantees everywhere: contracts, errors, authentication, observability, and tests.
- Teams that want framework portability to be proved without rewriting domain behavior.
Choose an Implementation¶
- Python quickstart - one endpoint in five minutes with FastAPI or Litestar.
- Node.js / TypeScript quickstart - a generated, verified service documented through OpenAPI.
- Scope, maturity, and exit - what MIC owns and what remains with the service.