Systems Don't Exist but Definitions Do

3 days ago 2
Oct 31, 2025

1. Fish Don't Exist (And Neither Does Your Code)

You've probably heard it: "Fish don't exist."

Not in the sense that there are no aquatic creatures. But in the sense that "fish" is a fuzzy, human-invented category with no clean boundaries. Lungfish are fish? Are whales fish?

The answer: Fish exist because we decided they do. We drew a line around a collection of creatures and said "that's a fish." The category is useful, but it's not discovered in nature—it's constructed by us.

2. Files Don't Exist Either

Your computer feels real. Files, folders, applications—you can see them on your desktop.

But they don't actually exist.

What actually exists: magnetic patterns on disk, electricity flowing through circuits.

What doesn't exist: the "file" abstraction.

When you double-click "myproject.txt", the OS executes complex instructions to read bytes and present them as a "file." The "file" is a definition. A useful fiction. If the OS changed its definition, the whole concept changes.

3. Your System Doesn't Exist Either

Now extend this to your software.

You believe your system has an OrderService, an order_created event, a payment-timeout error. But these don't actually exist.

What actually exists: functions executing, data transforming, bytes transmitting.

What doesn't exist: the categories you've imposed.

When you say "OrderService," you're drawing a circle around clustered functions. That's a definition, not a discovery. Tomorrow you could reorganize it completely.

If nothing fundamentally exists except the definitions we create, then the definitions themselves become the most important part of the system.

4. The Usual Mess

Most teams scatter definitions everywhere:

  • Component: class in code, deployment in K8s, box in diagram, paragraph in wiki
  • Error: exception in code, ticket in Jira, Slack thread, tribal knowledge
  • Event: Kafka schema, consumer code, API docs, that one email

Four definitions of the same thing. All drifting. All inconsistent.

5. Make Definitions Explicit

Stop pretending definitions are just "documentation." They're not describing the system—they are the system.

(s/def :error/code string?) (s/def :error/severity #{:low :medium :high :critical}) (s/def :error/retry? boolean?) (contract.type/def #{:semantic-namespace/error} [:error/code :error/severity :error/retry?]) (contract/def #{:semantic-namespace/error :domain.payment/timeout} {:error/code "PAY_TIMEOUT" :error/severity :high :error/retry? true})

Notice what just happened: The identity #{:semantic-namespace/error :domain.payment/timeout} reads like English:

"An error, in the payment domain, specifically a timeout"

The compound identity is the description. You don't need separate documentation—you can read it.

6. Why Compound Identities Matter

Traditional identities are flat strings. No semantics. No relationships.

Compound identities are sets of semantic aspects. Readable as plain English.

#{:semantic-namespace/error :domain.payment/timeout :severity/high}

Now the system can answer questions:

(find-docs #{:domain.payment}) (find-docs #{:severity/high}) (contract.type/instances #{:semantic-namespace/error})

The definitions are queryable. The identities are readable. The system is self-describing.

7. The Scale: What Gets Defined?

You might think: "Okay, but how many contract types do I really need?"

More than you think. And that's the point.

7.1. Short Term (First Sprint)

(contract.type/def #{:semantic-namespace/error} [...]) (contract.type/def #{:semantic-namespace/event} [...]) (contract.type/def #{:semantic-namespace/endpoint} [...]) (contract.type/def #{:semantic-namespace/component} [...]) (contract.type/def #{:semantic-namespace/permission} [...])

7.2. Mid Term (Growing System)

(contract.type/def #{:semantic-namespace/metric} [...]) (contract.type/def #{:semantic-namespace/command} [...]) (contract.type/def #{:semantic-namespace/query} [...]) (contract.type/def #{:semantic-namespace/job} [...]) (contract.type/def #{:semantic-namespace/validation} [...]) (contract.type/def #{:semantic-namespace/transformation} [...]) (contract.type/def #{:semantic-namespace/webhook} [...]) (contract.type/def #{:semantic-namespace/cache-strategy} [...]) (contract.type/def #{:semantic-namespace/rate-limit} [...]) (contract.type/def #{:semantic-namespace/circuit-breaker} [...]) (contract.type/def #{:semantic-namespace/retry-policy} [...]) (contract.type/def #{:semantic-namespace/saga} [...]) (contract.type/def #{:semantic-namespace/feature-flag} [...]) (contract.type/def #{:semantic-namespace/configuration} [...]) (contract.type/def #{:semantic-namespace/migration} [...]) (contract.type/def #{:semantic-namespace/integration} [...]) (contract.type/def #{:semantic-namespace/alert} [...]) (contract.type/def #{:semantic-namespace/dashboard} [...]) (contract.type/def #{:semantic-namespace/report} [...]) (contract.type/def #{:semantic-namespace/audit-log} [...])

7.3. The Realization

Each type might have 5-50 instances:

#{:semantic-namespace/error :domain.payment/timeout} #{:semantic-namespace/error :domain.payment/declined} #{:semantic-namespace/error :domain.order/not-found} #{:semantic-namespace/error :domain.order/invalid-state} #{:semantic-namespace/error :domain.shipping/address-invalid} #{:semantic-namespace/event :domain.order/created} #{:semantic-namespace/event :domain.order/cancelled} #{:semantic-namespace/event :domain.payment/succeeded} #{:semantic-namespace/endpoint :api.order/create} #{:semantic-namespace/endpoint :api.order/get} #{:semantic-namespace/endpoint :api.payment/charge}

A mid-sized project easily has 500-1000 definitions across 30-40 contract types.

Right now, these definitions are scattered. In your head. In code. In tickets. In Slack.

What if they were all in one place? Typed. Queryable. Readable.

(count @registry) (keys (clusters)) (->> (contract.type/instances #{:semantic-namespace/error}) (map contract/fetch) (filter #(= :critical (:error/severity %)))) (contract.type/instances #{:semantic-namespace/metric})

The scale isn't a burden. It's clarity.

Every one of those 847 things already exists in your system—you just haven't named them explicitly yet.

8. The Leap

Most teams think: System exists → document it → hope docs stay current

The truth: Define everything explicitly → system implements the definitions → query the definitions to understand the system

The definitions come first. Everything else flows from them.

9. What You Get

@registry (contract.type/instances #{:semantic-namespace/error}) #{:semantic-namespace/metric :domain.order/latency} (generate-api-from-definitions) (generate-docs-from-definitions) (generate-tests-from-definitions)

Your system isn't mysterious anymore. It's not hidden in code, configs, or people's heads.

It's explicit. It's unified. It's readable. It's just definitions.

All the way down.

Read Entire Article