TessariDB S3
Get started

Cluster and regions

Nodes, zones and regions, one layout at a time.

One node is a store. A set of nodes is a cluster that survives losing some of them. A set of clusters in different places is a store that survives losing a place. All three are the same binary and the same metadata schema in TessariDB.

Erasure sets

k data shards, m parity shards, one per node.

A cluster writes objects with a Reed-Solomon code k+m: four data and two parity, eight and four, any shape up to sixteen shards. Each object's shards go one per node in an erasure set, placed by a key all nodes share, so every node computes the same placement without asking anyone.

A write is acknowledged on its quorum: k shards durable, or k + 1 when k = m so that two halves of a split cluster cannot both accept a write. A read takes any k shards whose blocks verify.

Failure domains

A zone can go dark and every object still reads.

Each node names its zone: a rack, a room, a data centre. A layout never puts more of one object's shards in one zone than the parity can lose, so losing a whole zone leaves every object readable. The first layout is taken from the registered nodes in id order and passes over a node whose zone already holds m shards.

What a layout survives, by code and zone count.
CodeZonesSurvives
4 + 23 zones, 2 nodes eachany one zone, or any two nodes
8 + 44 zones, 3 nodes eachany one zone and one more node
6 + 33 zones, 3 nodes eachany one zone

Healing and layouts

Repairs and moves happen while the cluster serves.

A healing pass on every member rewrites missing or damaged shards of the objects listed for healing, one node at a time per object, under a claim in TessariDB. Shard bytes no object can reach any more are swept.

Root changes the layout in the console: a new layout is staged over the current version, judged against the registered nodes and their zones, and applied as the next version, or refused if anything changed meanwhile. Members then move objects written under older layouts, copying and verifying the shards whose node changes before switching the object, at a rate you set.

Membership

Members are admitted, not discovered.

  • A cluster begins from its founding members; any other node joins only when root approves it in the console, or with a one-time join token that binds the node's certificate.
  • Nodes talk to each other only over mutual TLS, each certificate issued for <node id>.peer.tessari-s3; a request is served only from an admitted member presenting the certificate for the node it claims to be.
  • A removed node is removed for good and never admitted again, and the removal reaches every node within five seconds.

Regions

Each region a cluster. Buckets replicate across them.

A region is a complete cluster: its own erasure sets in its own zones, and its own TessariDB members whose rows carry the REGION they stand in. A write in Frankfurt is acknowledged by Frankfurt's quorum and Frankfurt's metadata majority; it does not wait for an ocean.

Every bucket has a home region, chosen when it is created. Its replication rules name the regions that keep a copy and, optionally, the prefixes that travel. Replication runs after the home region has answered the client, carries versions and delete markers in commit order, and reports how far behind each destination is. Readers are served from the nearest region that holds the object; a region that is lost is replaced by promoting a destination to home.

Inside a region versus across regions.
Inside a regionAcross regions
Acknowledged whenthe write quorum and the metadata majority agreeafter the home region has answered
Protects againstlost drives, nodes and zonesa lost region
Orderone commit per versionversions and delete markers in commit order
Configured bythe layout: code, sets, zonesthe bucket's replication rules

Measured

The first numbers, with the conditions they were taken under.

Six tessaridb-s3 processes as one 4 + 2 cluster on a single Apple-silicon laptop, all six data directories on its one internal SSD, metadata in a TessariDB 0.34.0-beta node, release build, warm page cache; the median of three runs, and every GET returned exactly the bytes that were PUT. One laptop, not a production deployment: on macOS each sync flushes the whole drive's cache, so six nodes sharing one drive wait on each other.

tessaridb-s3-bench, 4 + 2 on one laptop.
4 KiB1 MiB64 MiB
PUT, one client81 ms83 ms525 ms
GET, one client2.3 ms2.7 ms59 ms
GET, most per second≈ 2,200≈ 1,640 MiB/s≈ 2,150 MiB/s
HEAD, most per second≈ 16,000≈ 15,500≈ 8,600