# Storage

HakoRun switches between ToriiDB and Redis with a build tag; both share one key layout and version semantics.

## Choosing a Backend

| Backend | Build | Location | Notes |
|---------|-------|----------|-------|
| ToriiDB | `make build` (default) | `~/.config/pardnchiu/hakorun` | Embedded store, no extra service |
| Redis | `make build redis` (`-tags redis`) | `REDIS_DB` on `REDIS_HOST:REDIS_PORT` | A failed `PING` at startup exits the process |

Both implement one interface (`internal/database/database.go`):

```go
type backend interface {
    Add(ctx context.Context, script Script) (int64, error)
    Get(ctx context.Context, path string, version int64) (*Script, error)
    Close() error
}
```

## Key Layout

`hash` is the hex string of `md5(path)`.

| Key | ToriiDB | Redis |
|-----|---------|-------|
| `meta:<hash>` | JSON: `path`, `language`, `latest`, `versions` | Hash: `path`, `language`, `latest` |
| `code:<hash>:<timestamp>` | Source string | Source string |
| Version list | `versions` array inside `meta` | Set `meta:<hash>:version` |

## Writes and Reads

| Operation | Behavior |
|-----------|----------|
| `Add` | ToriiDB writes `code` before `meta`, so `meta` never points at a missing version; Redis sends both in one pipeline |
| `Get` (`version = 0`) | Reads `latest` from `meta`, then fetches that `code` |
| `Get` (pinned) | Fetches `code:<hash>:<version>` directly; missing returns `assign version not found` |
| No `meta` | Returns `script not found`, which the handler turns into HTTP 404 |

Handlers apply a 5-second timeout to storage calls.

## Related Pages

- [Core Concepts](/core-concepts)
- [Configuration](/configuration)
