Skip to content
C.W.K.
Stream
Lesson 03 of 04 · published

Same-Process Still Needs a Contract

~12 min · boundary, coupling, fastapi

Level 0Cold Ash
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Sharing a process is no excuse to skip the contract. But a contract and HTTP are not the same thing."

The Tempting Shortcut

Bonfire's built-in UI and engine run close together. A browser UI can talk to the server's HTTP API, while tests or another shell may call the engine in-process. That proximity creates a temptation: import the internal model or repository directly because it is visible in the same codebase. The code is short and appears to work.

The problem is not every direct function call. The problem is which function the client knows. If the UI depends on internal types or storage, an engine refactor can break it even though no public contract changed. The model also travels through a private path no other client can use. If clients instead depend on a shared request-and-response port, the transport can vary: an HTTP adapter in the browser, an in-process adapter in tests or a same-process shell.

Design It Like Remote; Choose the Transport

The precise discipline is this: clients depend on the public contract, never engine internals. Define requests and responses that would still make sense across a machine boundary, then attach the transport that fits the deployment. Bonfire's browser UI crosses HTTP and proves that surface is sufficient. That does not require every in-process caller to pay for HTTP. The invariant is one contract, not one transport.

Code

One contract, multiple transport adapters·typescript
// WRONG — the UI depends on engine internals:
import { MusicModel } from "../../backend/model";
const song = MusicModel.load(trackId);

// RIGHT — the UI knows only the public contract:
interface BonfireClient {
  getTrack(id: string): Promise<TrackDTO>;
}

const httpClient: BonfireClient = {
  getTrack: (id) => fetch(`/api/v1/tracks/${id}`).then((r) => r.json()),
};

// A test or same-process shell can use an in-process adapter
// implementing the same contract. Transport changes; meaning does not.

External links

Exercise

Find two same-process parts joined by an internal import, global, or direct DB read. If they lived on different machines, what request and response would replace that reach? Write that contract first, then decide whether HTTP or an in-process adapter fits today's deployment.
Hint
The different-machines thought experiment discovers the contract; it does not command every call to use HTTP. If transport can change without changing request-and-response meaning, the boundary is doing its job.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Pippawarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.