# QuorumKV

QuorumKV is a distributed key-value store designed for small to medium clusters that need predictable reads and writes, replication, and simple operational controls without a heavyweight database stack.

It uses partitioned data placement, replica sets, quorum-based reads and writes, and a lightweight gossip layer for node membership. QuorumKV is intended for service configuration, metadata storage, coordination-adjacent workloads, feature flags, and other low-latency key-value use cases.

## Features

- Distributed key-value storage with automatic partitioning
- Configurable replication factor
- Quorum reads and writes
- HTTP and CLI interfaces
- Node discovery through static seed nodes
- Background anti-entropy repair
- Per-key TTL support
- Snapshot-based persistence
- Basic authentication support
- Prometheus-compatible metrics endpoint
- Graceful node join, leave, and shutdown

## Install

### From Source

```bash
git clone https://github.com/example/quorumkv.git
cd quorumkv
make build
```

The compiled binary will be available at:

```bash
./bin/quorumkv
```

### Using Docker

```bash
docker pull ghcr.io/example/quorumkv:latest
```

Run a single node:

```bash
docker run --rm \
  -p 8080:8080 \
  -p 9090:9090 \
  -v quorumkv-data:/var/lib/quorumkv \
  ghcr.io/example/quorumkv:latest
```

## Usage

### Start a Node

```bash
quorumkv server --config ./config/node-a.yaml
```

Example three-node cluster:

```bash
quorumkv server --config ./config/node-a.yaml
quorumkv server --config ./config/node-b.yaml
quorumkv server --config ./config/node-c.yaml
```

### Write a Key

```bash
curl -X PUT http://localhost:8080/v1/kv/users/42 \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada Lovelace","role":"admin"}'
```

### Read a Key

```bash
curl http://localhost:8080/v1/kv/users/42
```

### Delete a Key

```bash
curl -X DELETE http://localhost:8080/v1/kv/users/42
```

### Write With TTL

```bash
curl -X PUT "http://localhost:8080/v1/kv/sessions/abc123?ttl=15m" \
  -H "Content-Type: application/json" \
  -d '{"user_id":"42"}'
```

### CLI Examples

```bash
quorumkv put users/42 '{"name":"Ada Lovelace"}'
quorumkv get users/42
quorumkv delete users/42
quorumkv status
```

## Configuration

QuorumKV is configured with a YAML file.

```yaml
node:
  id: node-a
  bind_addr: 0.0.0.0
  advertise_addr: 10.0.1.10

http:
  enabled: true
  listen_addr: 0.0.0.0:8080

cluster:
  listen_addr: 0.0.0.0:9090
  seeds:
    - 10.0.1.10:9090
    - 10.0.1.11:9090
    - 10.0.1.12:9090

storage:
  data_dir: /var/lib/quorumkv
  snapshot_interval: 5m
  max_wal_size_mb: 256

replication:
  factor: 3
  read_quorum: 2
  write_quorum: 2
  repair_interval: 30s

limits:
  max_key_bytes: 1024
  max_value_bytes: 1048576
  request_timeout: 3s

auth:
  enabled: false
  token_file: /etc/quorumkv/tokens.yaml

metrics:
  enabled: true
  listen_addr: 0.0.0.0:9100
```

### Important Settings

| Setting | Description | Default |
| --- | --- | --- |
| `node.id` | Unique node identifier within the cluster | required |
| `node.advertise_addr` | Address other nodes use to reach this node | required |
| `cluster.seeds` | Initial peer addresses used for discovery | `[]` |
| `storage.data_dir` | Directory for snapshots and write-ahead logs | `/var/lib/quorumkv` |
| `replication.factor` | Number of replicas for each key range | `3` |
| `replication.read_quorum` | Replica responses required for a successful read | `2` |
| `replication.write_quorum` | Replica acknowledgements required for a successful write | `2` |
| `limits.max_value_bytes` | Maximum stored value size | `1048576` |
| `metrics.enabled` | Enables Prometheus metrics | `true` |

## Operational Notes

For production deployments, run at least three nodes across separate hosts or availability zones. The replication factor should not exceed the number of healthy nodes in the cluster.

A write is considered successful only after the configured write quorum acknowledges it. During partial outages, reads and writes may fail if quorum cannot be reached. Once nodes recover, background repair reconciles stale replicas using version metadata.

Before removing a node permanently, run:

```bash
quorumkv node drain node-a
```

This transfers ownership of the node's partitions before shutdown.