Skip to content

Why MIC?

MIC grew from pain observed across six production Python services: every service rewrote the same foundation, with variations that eventually made behavior diverge. The Node.js implementation does not copy Python line by line; it verifies that the same guarantees can remain explicit and idiomatic in another runtime.

Problems MIC Solves

1. The same foundation, rewritten differently

Symptom. Every service owns its route builder, response envelope, and error mapping. Two services return a domain failure as 400 or 409; another lets it bubble up as 500.

With MIC. Python uses HttpRouteSpec; TypeScript uses route(). In both cases, adapters share the contract, envelopes, and canonical mapping. A fix is made in the library and proved across every supported adapter.

2. Framework details leak into domain code

Symptom. Domain code imports fastapi.HTTPException, Express Request, or a NestJS decorator. Testing without starting the framework becomes difficult, and switching adapters requires use-case rewrites.

With MIC. Handlers receive validated data and return a canonical MIC result. Domain code knows only its contracts and domain errors. Parity tests then verify that every adapter exposes the same behavior.

3. Service authentication diverges in production

Symptom. A shared key is hardcoded, rotation breaks one call, or a token for service-A is accepted by service-B.

With MIC. ServiceAuthSigner and ServiceAuthVerifier bind each token to an audience, support controlled rotation, and enforce exact scopes. A compromised collector remains limited to explicitly granted operations.

4. Flattering tests do not prove the boundaries

Symptom. Coverage is high, but error mapping, a correlation header, or the archive that is actually published is never exercised.

With MIC. The Python implementation requires mirror tests with 100% line and branch coverage. The Node.js implementation runs native tests, inspects npm archives, then installs published packages into an empty project and verifies the generated service. Both prioritize public behavior.

5. Services communicate through a shared database

Symptom. Two services share one table. A migration from the first can break the second without any change to its code.

With MIC. Each service owns its data. Communication uses signed HTTP, versioned events, or explicitly synchronized read models. See the shared-database anti-pattern.

6. Adding a service consumes domain-delivery time

Symptom. The first endpoint arrives after days of copying setup, authentication, health checks, configuration, and repetitive tests.

With MIC. The Python cookiecutter and Node.js @mic-struct/create-mic-service generate a verifiable service with liveness, readiness, observability, an example module, and tests. The Node generator also provides an OpenAPI contract and operator CLI.

Problems MIC Does Not Solve

  • MIC does not write your domain. Product rules, invariants, and decisions remain in your service.
  • MIC does not deploy for you. Kubernetes, Compose, a VPS, and supervision remain infrastructure choices.
  • MIC does not write migrations. Alembic, Node.js tooling, and engine-specific SQL remain service responsibilities.
  • MIC does not operate observability for you. Logging, metric, and tracing primitives are provided; backends, retention, alerts, and SLOs remain yours.
  • MIC is not your infrastructure scheduler. It provides locking, checkpoints, execution tracking, and silence detection; infrastructure triggers and supervises the process.
  • MIC cannot make a raw store safe by magic. Organization-scoped relational views fail without context, but the application must inject them everywhere and may add database policies.
  • MIC does not replace Python, TypeScript, or their libraries. Pydantic, SQLModel, FastAPI, Node HTTP, and Node frameworks remain building blocks; MIC organizes their boundaries.

The scope, maturity level, and exit strategy are documented separately so silence cannot be mistaken for a promise.

How to Know Whether MIC Is for You

You are the target audience if:

  • you have multiple Python services, TypeScript services, or both, and they communicate;
  • you want the same quality baseline without copy-paste;
  • you accept strict contracts and demanding tests as design constraints;
  • you want framework portability to be proved;
  • you want contracts that humans and machines can read.

MIC will provide less value if:

  • you have one isolated service with no external boundary;
  • you are exploring a disposable prototype whose shape will change completely;
  • you reject strict contracts or tests of error paths;
  • you require a framework without a MIC adapter and do not want to write that adaptation.

Start with the Python quickstart or the Node.js / TypeScript quickstart.