Skip to content
Asmar.
§ 06 — Method

Three convictions
I keep returning
to.

I've designed software in seven domains across twelve years — central banks, donor programs, robo-advisory, large-cap insurance, and the five products of the Ghasi suite. The stacks change. The contexts change. The convictions don't.

1

The domain layer is sacred.

The single largest source of architectural decay I've seen is the slow leak of framework concerns into the domain. A NestJS decorator here, a Drizzle import there, a Kafka envelope baked into a value object — each one looks like a small convenience at the time. A year later, the domain layer doesn't compile without the framework, can't be tested without booting the infrastructure, and can't be reasoned about without remembering which version of which adapter is in scope.

So I keep the domain pure. Pure TypeScript. No NestJS, no ORM, no broker, no provider SDK in the import graph. Aggregates, value objects, domain events, and repository interfaces — that's it. The application layer composes use-cases against those interfaces. The infrastructure layer implements them with whatever the world happens to be running this year.

The cost is more files, more interfaces, and the discipline to refuse the convenient import. The win is that every adapter — the database, the queue, the LLM provider, the search engine — becomes replaceable without touching the part of the code that encodes the business.

2

Multi-tenancy is not a feature flag.

Most “multi-tenant” systems are actually single-tenant systems with a WHERE clause. The application code filters by tenant; the database trusts the application. The first time someone forgets the filter, two tenants see each other.

Real multi-tenancy is enforced at three layers, simultaneously. At the domain, tenant identity is a first-class invariant of every aggregate. At the database, row-level security is on; service roles do not have BYPASSRLS; every transaction sets app.current_tenant_id first. At the transport, every event envelope and every API request carries a tenant header — the JWT claim, the path parameter, and the envelope header all agree before the request reaches a handler.

The cost is plumbing in three places. The win is that “multi-tenant data leak” stops being a class of bug your system can have.

3

Architects who don't ship lose calibration.

There's a particular kind of architecture document that reads beautifully and is entirely wrong. It's wrong because the author hasn't built anything in the constraints they're prescribing for years, and the constraints they remember are no longer the constraints that exist.

The cure isn't more diagrams. The cure is shipping. Not as a side hobby — as a structural part of the architecture practice. I keep the Ghasi suite running for this reason: five product platforms with real domain layers, real outboxes, real CI gates, real on-call. It's how I keep my hands close enough to the code that when I'm at the Architecture Review Board recommending an approach, I'm recommending it from inside the constraint, not above it.

How I run an engagement

Independent engagements move through four phases. The shape stays the same; the depth scales with the engagement size.

  1. PHASE — 01

    1–2 weeks

    Listen.

    Read everything: the existing architecture documents, the codebase, the recent post-mortems, the roadmap, the team's chat archives if they're shared. Sit in on a sprint planning, a retro, an on-call handover. Talk to three engineers who weren't put forward by the sponsor. The goal is to understand what's actually true, not what the deck says.

  2. PHASE — 02

    2–3 weeks

    Map.

    Produce a context map of the current bounded contexts (whether the team uses that vocabulary or not). Trace the integration patterns — what's synchronous, what's eventual, what's fragile. Identify the two or three architectural decisions in the next ninety days that will compound the most.

  3. PHASE — 03

    1–2 weeks

    Decide.

    Write the ADRs. Each one names the decision, the alternatives I considered, the tradeoffs, and the conditions under which I'd revisit it. Walk the team through every ADR. Argue the cases out loud. Revise. Sign.

  4. PHASE — 04

    varies

    Hand off, supervise, or lead.

    Three exits: hand-off (advisory engagement closes here), supervise (I stay close to delivery for a quarter, reviewing the implementation against the blueprint), or lead (I take the architect-of-record role through the build).

What I produce

  • — A context map of bounded contexts and their relationships.
  • — Service blueprints with API contracts and event schemas.
  • — Architectural decision records (ADRs), versioned in the repo.
  • — A risk register and a sequencing plan.
  • — POVs and POCs where the answer is genuinely unknown.

What I won't do

  • — Write architecture documents that nobody reads. Every artifact is anchored to a decision the team has to make.
  • — Stay attached to a recommendation past its evidence. If the context changes, the ADR gets updated.
  • — Pretend a buy-vs-build call has a single right answer. It rarely does. I'll lay out the tradeoffs and let the team own the call.

Want me to run one of these?