MapStore is a local, filesystem‑backed map database with pluggable codecs (JSON or custom), optional per‑key encryption via the OS keyring, and optional full‑text search via SQLite FTS5.
-
File store
- It keeps a
map[string]anyin sync with files on disk, the file can be encoded as JSON (inbuilt), or any format using a custom file encoder/decoder. - It is a thread-safe map store with atomic file writes and optimistic concurrency.
- Pluggable codecs for both keys and values inside the map, including an encrypted string encoder backed by
github.com/zalando/go-keyring. - Listener hooks so callers can observe every mutation written to disk.
- Optional SQLite FTS5 integration for fast search, with helpers for incremental sync.
- It keeps a
-
Directory store: A convenience manager that partitions data across subdirectories and paginates listings.
-
Pure Go implementation with no cgo, compatible with Go 1.25+.
-
File encoders
- Supply your own
IOEncoderDecoderviaWithFileEncoderDecoder. - JSON file encode/decode - use the inbuilt
jsonencdec.JSONEncoderDecoderto encode/decode files as JSON.
- Supply your own
-
Encode key or value at sub-path
- Override encoding of specific keys or values with
WithKeyEncDecGetterorWithValueEncDecGetter. - Value encryption - use the inbuilt
keyringencdec.EncryptedStringValueEncoderDecoderto transparently store sensitive string values through the OS keyring.
- Override encoding of specific keys or values with
-
Directory Partitioning
- Swap in your own
PartitionProviderto control directory layout. - Month based partitioning - use the inbuilt
dirpartition.MonthPartitionProviderto split files across month based directories.
- Swap in your own
-
File naming
- The file store is opaque to filenames, allowing for any naming scheme.
- The directory store uses a
FileKeybased design to allow for control of encoding and decoding of data inside file names for efficient traversal. - UUIDv7 based filename provider - use the inbuilt UUIDv7 based provider to derive and use, collision free and semantic data based filenames.
-
File change events
- Custom listeners can be plugged into the file store to observe file events.
- Pluggable Full text search
- Inbuilt, pure go, sqlite backed (via glebarez driver + modernc sqlite), fts engine.
- Pluggable iterator utility
ftsengine.SyncIterToFTSfor efficient, incremental index updates.
go get github.com/ppipada/mapstore-go- Single file store: see ExampleMapFileStore.
- Managing files inside a directory: see ExampleMapDirectoryStore.
- A full store with JSON encode decode, month partitioning, uuid filenames and FTS enabled: see ExampleMapDirectoryStore_full.
- Additional samples can be seen in integration tests under integration tests.
github.com/ppipada/mapstore-go— file and directory stores, options, events, and types.github.com/ppipada/mapstore-go/jsonencdec— JSON file encoder/decoder.github.com/ppipada/mapstore-go/keyringencdec— per-value encryption (AES‑256‑GCM; key in OS keyring).github.com/ppipada/mapstore-go/dirpartition— partitioning strategies (month/no-op).github.com/ppipada/mapstore-go/uuidv7filename— UUIDv7‑backed filename helpers.github.com/ppipada/mapstore-go/ftsengine— FTS5 engine and sync helpers.
MapStore uses optimistic concurrency when writing files:
- Writes create a deep copy of the in‑memory map, encode it (value encoding first, then key encoding), and atomically rename a temp file into place.
- Before writing, the store compares current file
statto a remembered snapshot. If it changed,SetAllandDeleteFilereturn a conflict error.SetAllretries a few times automatically; key‑level mutations (SetKey/DeleteKey) honor theAutoFlushsetting and propagate conflict errors from the internal flush. - This is best‑effort across processes. Two writers racing between the pre‑write CAS check and
renamemay still result in last‑writer‑wins. If you need stronger cross‑process guarantees, coordinate at the application level.
keyringencdec.EncryptedStringValueEncoderDecoderuses the OS keyring to store the AES‑256 key.- In headless or container environments, ensure a compatible keyring backend is available, or avoid using the keyring‑based encoder.
- Formatting follows
gofumptandgolinesviagolangci-lint, which is also used for linting. All rules are in .golangci.yml. - Useful scripts are defined in
taskfile.yml; requires Task.
MapStore is released under the MIT License.