Archtin
All articles
ArchitectureSystem DesignScalability11 min read

Space-Based Architecture: Removing the Database From the Hot Path

When concurrency spikes make the database the ceiling, space-based architecture keeps working data in a replicated in-memory grid and persists asynchronously. It is how ticketing, betting and trading systems survive on-sale moments.

The problem it solves

Most architectures scale the application tier and quietly assume the database will keep up. For workloads with extreme, unpredictable concurrency — a concert on-sale, a betting market during a goal, a flash sale — it will not. You hit connection limits, lock contention on the hot rows, and replication lag, and no amount of application replicas helps.

Space-based architecture (also called cloud or tuple-space architecture) removes the synchronous database from the request path entirely. Working state lives in a replicated in-memory data grid; durability happens asynchronously behind it.

Core insight
The database stops being the system of record for the request path and becomes the system of record for history. Reads and writes during the spike touch memory only.

The four components

ComponentRole
Processing unitThe deployable: application logic plus an in-memory copy of the data it needs. Scaled by adding identical units.
Virtualised middlewareThe fabric: messaging grid (routes requests), data grid (replicates state), processing grid (coordinates multi-unit work), deployment manager (scales units on load).
Data pumpAsynchronously ships changes from memory to durable storage, usually via a durable queue.
Data writer / readerPersists what the pump sends; reads seed a starting or restarting unit's in-memory state.

How a request flows

client
  -> messaging grid  (route by partition key, e.g. eventId)
  -> processing unit N
       read  : local in-memory grid  (microseconds)
       write : update memory + replicate to peers
       emit  : change record -> durable queue
  <- response

           durable queue
                 |
            [ data pump ]
                 v
            database / warehouse   (seconds behind, and that's fine)
No synchronous database access anywhere in the request path.

Latency drops by orders of magnitude because the slowest step is now memory replication rather than a disk-backed transaction. Throughput scales by adding processing units, since each holds its data locally.

Replication and cache coherence

The hard part. Every processing unit holding a copy of the same data means updates must propagate, and how you do it determines your consistency guarantees:

  • Full replication: every unit holds everything. Simple reads, but memory cost and replication traffic grow with unit count. Only workable for small datasets.
  • Partitioned (sharded) grid: each unit owns a key range; requests are routed by partition key. This is the standard approach and the reason the messaging grid exists.
  • Partitioned with backups: each partition has one primary and one or more backups on other units, so a unit failure does not lose the partition. This is what production grids (Hazelcast, Ignite, Coherence, GigaSpaces) do by default.

For contended counters — seats remaining, stock left — route all writes for a key to its owning primary. Single-writer-per-partition converts a distributed consistency problem into a local one, which is the whole trick.

Durability and the data pump

  1. A write updates memory and its backups synchronously (fast, in-datacentre), and emits a change record to a durable queue.
  2. The data pump consumes the queue and writes to the database at whatever rate the database can manage. Backlog during a spike is expected and drains afterwards.
  3. The window between memory commit and disk commit is your real durability risk. Bound it: replicate to at least two units in different failure domains, use a durable queue rather than in-process buffering, and measure pump lag as a first-class SLO.
  4. On restart, a unit rehydrates its partition from the database plus the unconsumed queue tail.

Sizing and partitioning

  • Only the working set goes in memory. Today's events, open positions, active carts — not five years of history.
  • Pick a partition key with natural isolation (eventId, matchId, accountId) so cross-partition operations are rare. Anything requiring a distributed transaction across partitions undoes the performance win.
  • Watch for hot partitions. One blockbuster event can saturate a single primary; sub-partition it (seat blocks, price bands) if the domain allows.
  • Scale by traffic prediction and by load. The deployment manager adds units as concurrency rises, but grid rebalancing itself costs time — pre-warm before a known on-sale.

Trade-offs and failure modes

PropertyResult
LatencyExcellent — memory-speed reads and writes
ElasticityExcellent — add units, no database bottleneck
DurabilityWeaker — a bounded window of unpersisted state
ConsistencyStrong within a partition, eventual across the grid and the database
Operational complexityHigh — grid tuning, split-brain, rebalancing, memory pressure
CostHigh — RAM is expensive relative to disk
Query flexibilityPoor — ad-hoc reporting must run off the persisted store

The nastiest failure is a network partition splitting the grid: two halves each believe they own a partition and both accept writes. Production grids use quorum-based membership and will refuse to serve a minority partition. Configure this deliberately — the default is not always the safe one.

Interview framing

Strong answer

"Ticket on-sale is a 60-second spike with severe contention on a few thousand rows, so a database in the write path is the ceiling. I'd use a space-based design: processing units partitioned by eventId, each owning the seat inventory for its events in memory with a synchronous backup replica, all writes for an event routed to its primary so seat allocation is a local operation, and a data pump writing to Postgres asynchronously via a durable queue. We pre-warm units before the on-sale. The trade is a durability window of a second or two and the operational cost of running a grid — acceptable, because the alternative is a hard cap on concurrent buyers."

Follow-ups

  • What happens if a processing unit dies with unpersisted writes?
  • How do you prevent two units selling the same seat?
  • How does this compare with just using Redis plus a queue?

Keep reading

Suggested next articles based on this one.

Design it, don't just read it.

Practise LLD and system design problems with structured rubrics and AI feedback.

Start practising free