A typed key-value store with an HTTP API, backed by redb.
Data is organized into cabinets (databases) and shelves (typed tables). Each shelf enforces a fixed key type and value type, so type mismatches are caught at write time rather than read time.
- Cabinet — an isolated redb database file. Create as many as you need.
- Shelf — a typed table inside a cabinet. Each shelf has a fixed key type (
String,Int,Number) and value type (String,Int,Number,Object,Byte). - System store — internal metadata database that tracks all cabinets and their shelves.
cargo build --release
./target/release/carmineBy default, Carmine listens on 0.0.0.0:3000 and stores data in ./data.
Carmine loads configuration from CLI flags, environment variables, and/or a TOML config file (searched as carmine.toml, config.toml, .carmine.toml in the working directory).
| Setting | CLI flag | Env var | TOML path | Default |
|---|---|---|---|---|
| Data directory | --data-dir |
CARMINE_DATA_DIR |
storage.data_dir |
./data |
| Bind address | --bind |
CARMINE_BIND |
server.bind |
0.0.0.0:3000 |
| Cabinet cache size | --cabinet-cache |
CARMINE_CABINET_CACHE_SIZE |
cache.cabinet_size |
64 MB |
| System cache size | --system-cache |
CARMINE_SYSTEM_CACHE_SIZE |
cache.system_size |
8 MB |
| Durability | --durability |
CARMINE_DURABILITY |
storage.durability |
immediate |
| Log level | --log-level |
CARMINE_LOG_LEVEL |
logging.level |
info |
Example carmine.toml:
[server]
bind = "127.0.0.1:8080"
[storage]
data_dir = "/var/lib/carmine"
durability = "immediate" # or "none" for faster writes without fsync
[cache]
cabinet_size = 67108864
system_size = 8388608
[logging]
level = "info"POST /system/cabinets
{ "name": "my_cabinet" }{
"id": 1234567890,
"name": "my_cabinet",
"path": "./data/cabinet_1234567890",
"shelves": []
}GET /system/cabinets
[
{
"id": 1234567890,
"name": "my_cabinet",
"path": "./data/cabinet_1234567890",
"shelves": [
{ "name": "users", "key_type": "String", "value_type": "Object" }
]
}
]GET /system/cabinets/:name
DELETE /system/cabinets/:name
POST /system/cabinets/:name/clean
POST /system/cabinets/:name/shelves
{
"name": "users",
"key_type": "String",
"value_type": "Object"
}{ "name": "users", "key_type": "String", "value_type": "Object" }Valid key types: String, Int, Number
Valid value types: String, Int, Number, Object, Byte
GET /system/cabinets/:name/shelves
DELETE /system/cabinets/:name/shelves/:shelf
All data operations go through /v1/:cabinet/:shelf/.
POST /v1/my_cabinet/users/set
{ "key": "alice", "value": {"role": "admin", "active": true} }Response: 204 No Content
POST /v1/my_cabinet/users/put
{ "key": "alice", "value": {"role": "admin", "active": true} }Response: 204 No Content
POST /v1/my_cabinet/users/get
{ "key": "alice" }{ "value": {"role": "admin", "active": true} }Returns null for the value if the key does not exist.
POST /v1/my_cabinet/users/delete
{ "key": "alice" }Response: 204 No Content
POST /v1/my_cabinet/users/exists
{ "key": "alice" }{ "exists": true }GET /v1/my_cabinet/users/all
{ "entries": [["alice", {"role": "admin"}], ["bob", {"role": "user"}]] }GET /v1/my_cabinet/users/keys
{ "keys": ["alice", "bob"] }GET /v1/my_cabinet/users/values
{ "values": [{"role": "admin"}, {"role": "user"}] }GET /v1/my_cabinet/users/count
{ "count": 2 }POST /v1/my_cabinet/users/range
{ "start": "a", "end": "c" }{ "entries": [["alice", {"role": "admin"}], ["bob", {"role": "user"}]] }POST /v1/my_cabinet/users/batch/set
{
"entries": [
["alice", {"role": "admin"}],
["bob", {"role": "user"}]
]
}Response: 204 No Content
POST /v1/my_cabinet/users/batch/put
Same format as batch set.
POST /v1/my_cabinet/users/batch/get
{ "keys": ["alice", "bob", "unknown"] }{ "values": [{"role": "admin"}, {"role": "user"}, null] }POST /v1/my_cabinet/users/batch/delete
{ "keys": ["alice", "bob"] }Response: 204 No Content
GET /health
Returns OK.
# Create a cabinet
curl -X POST http://localhost:3000/system/cabinets \
-H 'Content-Type: application/json' \
-d '{"name": "myapp"}'
# Create a shelf with string keys and object values
curl -X POST http://localhost:3000/system/cabinets/myapp/shelves \
-H 'Content-Type: application/json' \
-d '{"name": "users", "key_type": "String", "value_type": "Object"}'
# Insert a record
curl -X POST http://localhost:3000/v1/myapp/users/set \
-H 'Content-Type: application/json' \
-d '{"key": "alice", "value": {"email": "alice@example.com", "plan": "pro"}}'
# Read it back
curl -X POST http://localhost:3000/v1/myapp/users/get \
-H 'Content-Type: application/json' \
-d '{"key": "alice"}'
# => {"value":{"email":"alice@example.com","plan":"pro"}}
# Batch insert
curl -X POST http://localhost:3000/v1/myapp/users/batch/set \
-H 'Content-Type: application/json' \
-d '{"entries": [["bob", {"email": "bob@example.com"}], ["carol", {"email": "carol@example.com"}]]}'
# List all keys
curl http://localhost:3000/v1/myapp/users/keys
# => {"keys":["alice","bob","carol"]}
# Count
curl http://localhost:3000/v1/myapp/users/count
# => {"count":3}