Hanzi Design
Concept exist

exist · preserve

Exist + Child

Existence is not creation but persistence. A file exists on disk, a record exists in database, a session exists in memory. The question is not how it came into being but whether it continues to be. Existence checking precedes every operation: does this resource exist before attempting to use it? Existence is binary—the thing is or is not—but detection is probabilistic. The check says "exists now" but cannot guarantee "will exist when accessed." Race conditions occur in the gap between existence verification and existence assumption. Design must handle the case where existence is confirmed but then vanishes before use.

Existence Checking

Before accessing a resource, verify it exists. Does the file exist before reading? Does the user account exist before authenticating? Does the API endpoint exist before calling? The existence check prevents errors from accessing non-existent resources.

But existence checks are not atomic with subsequent operations. The file exists during the check, then gets deleted before the read. The race condition is fundamental: checking and using are separate operations with time gap between them. Another process can modify existence state in that gap.

The solution is either atomic check-and-use operations (open file for reading returns error if non-existent, combining check and use) or exception handling (attempt the operation, handle the failure if resource doesn't exist). Pure existence checking followed by separate use assumes static world, which is false assumption in concurrent systems.

Persistence Mechanisms

Existence over time requires persistence mechanisms. Memory-based existence vanishes when process dies. Disk-based existence survives process death. Database-based existence survives system death. Cloud-based existence survives datacenter death. The persistence mechanism determines existence durability.

Choosing persistence mechanism means choosing what failure modes end existence. In-memory cache exists until process restart. Local disk storage exists until disk failure. Replicated database exists until all replicas fail simultaneously. The cost of persistence increases with durability, but so does existence reliability.

The error is using fragile persistence for data that needs durability, or expensive persistence for data that doesn't. Session tokens can be in-memory; user accounts need database persistence. Temporary files can be local; critical documents need replicated storage. Match persistence mechanism to existence requirements.

Existence Proofs

Some systems require proof of existence rather than assuming it. Merkle trees prove data existed at specific time. Blockchain proves transaction existed in ledger. Signed timestamps prove document existed before signature date. The proof is cryptographic—mathematically verifiable rather than trust-based.

Existence proofs matter when existence itself is disputed. Did this data exist before it was supposedly modified? Was this transaction recorded before the dispute arose? Can you prove this document existed at claimed time? The proof provides non-repudiable evidence.

Designing systems that require existence proofs means building verification into data structures from the start. Retrofitting existence proofs onto systems designed without them is difficult or impossible. The choice is made during initial architecture, not later.

Existence vs. Liveness

A zombie process exists but is not live. A crashed service exists (files on disk, configuration in place) but is not running. Existence is weaker condition than liveness. The resource is present but not necessarily functional.

Health checks verify liveness, not just existence. Is the service responding to requests, or just occupying a port? Is the database accepting queries, or just consuming memory? Existence checking returns true for dead-but-present resources; liveness checking requires functional verification.

Monitoring systems must distinguish existence failures (resource completely absent) from liveness failures (resource present but non-functional). The remediation differs: existence failures need creation or restoration, liveness failures need restart or repair. Confusing the two leads to wrong responses.

The Cache Existence Problem

Caches create existence ambiguity. The data exists in cache but not in origin. The data exists in origin but not in cache. The data exists in both but versions differ. Which existence is authoritative?

Cache invalidation is existence synchronization. When origin data changes, cache existence becomes stale. The cached version still exists but no longer represents current state. The system must invalidate (delete) cache existence or update it to match origin.

The classic problems—cache invalidation and naming—both relate to existence. Invalidation is existence lifecycle management. Naming is existence identification. Getting both right is famously difficult because existence in distributed systems is fundamentally ambiguous.

Soft Delete vs. Hard Delete

Soft delete marks resource as deleted but leaves it existing. The record gets deleted_at timestamp but remains in database. The file moves to trash but stays on disk. Existence continues but visibility changes.

Hard delete removes existence entirely. The record is deleted from database. The file is unlinked from filesystem. Recovery is impossible or requires backup restoration. Existence truly ends.

Soft delete enables undo and audit trails at cost of storage and query complexity. Queries must filter soft-deleted records. Storage accumulates deleted-but-existing resources. Hard delete is cleaner but irreversible. The choice depends on whether mistakes are more costly than storage.

Idempotent Creation

Creating something that already exists should be safe. Mkdir should succeed if directory exists. Insert-or-update should work whether record exists or not. Idempotent operations handle existence uncertainty gracefully.

Non-idempotent creation fails if resource exists. This creates retry problems: creation failed, retry creation, fail because resource exists from first attempt. The client cannot distinguish "created successfully" from "already existed" without separate existence checking.

Designing for idempotence means making existence a postcondition rather than precondition. The operation ensures resource exists afterward, regardless of whether it existed before. This simplifies error handling and enables safe retries.

Eventual Consistency and Existence

In eventually consistent systems, existence is not globally synchronized. The resource exists in one datacenter but not another. Existence check in region A returns true; same check in region B returns false. Both are correct for their local view.

The existence ambiguity resolves eventually as updates propagate. The resource will exist everywhere once replication completes. But during propagation window, existence state is uncertain from global perspective.

Designing for eventual consistency means accepting existence ambiguity. Operations cannot assume global existence consensus. The system must handle "exists here but not there" scenarios gracefully. Strong consistency eliminates ambiguity but reduces availability and performance.

Reference Counting

How long should a resource exist? One approach is reference counting: resource exists while references to it exist, dies when last reference is removed. Shared memory, file handles, object references—all can use reference counting for existence management.

Reference counting automates existence lifecycle. Creators don't explicitly destroy resources; they release references. When count reaches zero, automatic cleanup occurs. This prevents both premature deletion (while references exist) and resource leaks (after all references gone).

But reference counting has problems. Circular references prevent count from reaching zero. Distributed reference counting requires coordination overhead. Manual reference management is error-prone. Garbage collection is alternative approach that trades performance for correctness.

Existence Monitoring

How do you know a resource still exists? Active monitoring periodically checks. Passive monitoring assumes existence until failure detected. Active monitoring catches failures faster but creates overhead. Passive monitoring is efficient but slow to detect problems.

The choice depends on failure cost. Critical resources need active monitoring—frequent checks to detect existence loss quickly. Non-critical resources can use passive monitoring—assume existence until operation fails, then investigate.

Monitoring frequency trades overhead against detection latency. Check every second for fast detection and high overhead. Check every hour for low overhead and slow detection. The appropriate frequency depends on how quickly existence loss must be detected and remediated.