When mainzelmen needed user isolation, I reached for the same boundary I'd built in cloudapps - an Engine that pre-configures every dependency for one tenant so domain code never asks which database it's writing to. Different product, no shared code, completely different mechanics. The boundary held. What one implementation alone couldn't show me was how much of it was incidental.
Different mechanics, same boundary
mainzelmen processes email attachments for individual Google users. The tenant identity is a Gmail address from an OAuth login, and a SHA-256 hash of that address becomes the database filename. Inside ServiceFactory:
def _user_hash(email: str) -> str:
return hashlib.sha256(email.encode()).hexdigest()[:16]
@property
def db_path(self) -> Path:
auth = self._get_auth()
if auth is not None:
return _get_data_dir() / f'{_user_hash(auth.email)}.db'
return _get_data_dir() / 'default.db'
Python
No tenant header, no URL path segment, no class hierarchy. A FastAPI dependency pulls credentials from the session and constructs a fresh ServiceFactory per request. That factory builds repositories bound to the user's database, a Gmail client scoped by the user's OAuth token, a Drive filesystem for the user's folders. What reaches the domain is a Context:
@dataclass
class Context:
mail_client: MailClient
rule_checker: RuleChecker
file_system_factory: Callable[[str], FileSystem]
repository: AttachmentOutcomeRepository
Python
No email field. No user identifier. A command that plans which attachments to import calls ctx.rule_checker.check(attachment) and ctx.file_system_factory(folder) without knowing whose rules or whose Drive it touches.
What two implementations reveal
cloudapps does this with a cached engine resolved from a URL path. mainzelmen does it with a per-request factory resolved from a session cookie. The machinery differs in every detail, but the shape is the same: at the infrastructure-domain boundary, a container pre-scopes every dependency, and downstream code never participates in isolation.
Two codebases with the same boundary and different mechanics make it possible to separate what's essential from what's incidental. What varies:
- cloudapps resolves the tenant from a URL path, mainzelmen from an OAuth email. A subdomain or API key would work the same way.
- One names databases by tenant directory, the other by hashed filename.
- cloudapps caches one engine per tenant. mainzelmen constructs a fresh factory per request.
- Sixteen services in the container vs four.
What doesn't: a single object at the boundary that pre-configures all dependencies for one tenant before any business logic runs. The rest is a consequence of the specific product, not of the isolation strategy.
The first implementation couldn't tell me this. cloudapps' Engine was a solid answer to a multi-tenancy problem, but from one codebase alone I couldn't distinguish the essential shape from the specifics of that product. Building the same boundary a second time - different product, different identity mechanism, different storage strategy - is what separated the two. The isolation test captures it:
factory_a = ServiceFactory(GoogleAuth('token', 'refresh', 'alice@example.com'))
factory_b = ServiceFactory(GoogleAuth('token', 'refresh', 'bob@example.com'))
assert factory_a.db_path != factory_b.db_path
Python
Different credentials in, different databases out. Everything downstream is identical.
The first implementation is a solution. The second is validation.