Memory Store
In-memory store for development, testing, and prototyping.
The memory store keeps all data in Go maps protected by a sync.RWMutex. It requires zero configuration and is the default store for unit tests.
When to use
- Unit tests — fast, deterministic, no external dependencies.
- Local development — get started without setting up a database.
- Prototyping — validate business logic before choosing a persistence layer.
- CI pipelines — no database containers needed.
Data is lost when the process exits.
Configuration
The memory store has no configuration. Just call New():
import "github.com/xraph/ctrlplane/store/memory"
s := memory.New()Or use it with the app:
cp, err := app.New(
app.WithStore(memory.New()),
)Internals
| Aspect | Detail |
|---|---|
| Concurrency | sync.RWMutex — reads can run concurrently, writes are exclusive |
| Indexing | Map keys by ID string; linear scan for list/filter operations |
| Migrate | No-op |
| Ping | No-op (always succeeds) |
| Close | No-op |
Data layout
Entities are stored in typed maps keyed by their TypeID string:
instances map[string]*instance.Instance
deployments map[string]*deploy.Deployment
releases map[string]*deploy.Release
// ...Secrets use a composite key instanceID:key for direct lookup by instance and key name.
Limitations
- No persistence — all data lost on restart.
- No indexing — list operations are O(n) scans.
- Single process — cannot be shared across multiple instances.
- No transactions — individual operations are atomic via mutex, but there are no multi-operation transactions.
Comparison
| Feature | Memory | Badger | Bun | MongoDB |
|---|---|---|---|---|
| Setup | None | Path only | DSN | URI |
| Persistence | No | Yes | Yes | Yes |
| Multi-process | No | No | Yes | Yes |
| Query flexibility | Low | Low | High | High |
| Best for | Tests | Embedded | Production SQL | Production NoSQL |