FlashDB in Go: in-memory key-value store with optional persistence

Tech reviewed: Deepak Prasad
FlashDB in Go: in-memory key-value store with optional persistence

FlashDB is a small embedded golang key value store. If you are comparing golang in memory database options, it offers Redis-style string, hash, set, and sorted-set style operations as composable Go packages, with an optional append-only log for durability. Search queries such as in memory database golang, golang in memory db, go in memory database, or golang in-memory database often mean either pure RAM for the lifetime of the process or memory-first with disk backup—FlashDB supports both by toggling Config.Path. This memory db tutorial walks through install, opening a DB, and string SET, GET, and DELETE inside transactions.

Tested with Go 1.24 on Linux against github.com/arriqaaq/flashdb v0.1.6.


FlashDB architecture (in-memory core, optional log)

FlashDB combines in-memory structures with supporting libraries:

  • Set — unordered string collections and set algebra.
  • ZSet — sorted sets with scores (skiplist-backed).
  • ART string index — radix-tree style storage for string keys.
  • Hash — field/value maps similar to Redis hashes.
  • Append-only log (aol) — immutable log used when persistence is enabled.

For diagrams and deeper internals, see the FlashDB repository.


Install FlashDB (go get)

From a new module:

text
go mod init example.com/flashdemo
go get github.com/arriqaaq/[email protected]

Typical resolver output (trimmed):

text
go: added github.com/arriqaaq/aol v0.1.2
go: added github.com/arriqaaq/art v0.1.1
go: added github.com/arriqaaq/flashdb v0.1.6
go: added github.com/arriqaaq/hash v0.1.2
go: added github.com/arriqaaq/set v0.1.2
go: added github.com/arriqaaq/zset v0.1.2

Create and open a database

The main handle is *flashdb.FlashDB. Call flashdb.New with a flashdb.Config:

  • Path — directory for append-only logs. Use "" for a pure in-memory database (no files, no replay after exit).
  • EvictionInterval — interval in seconds between TTL sweeps for expired keys (set 0 to disable background eviction workers).
  • NoSync — when Path is set, NoSync: true skips fsync after writes for speed at the cost of durability if the host crashes.
go
package main

import (
	"log"

	"github.com/arriqaaq/flashdb"
)

func main() {
	config := &flashdb.Config{
		Path:             "/tmp/flashdb-demo",
		EvictionInterval: 10,
	}
	db, err := flashdb.New(config)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
}

For a RAM-only golang in memory db during development, point Path at "" (and still set EvictionInterval if you rely on TTL expiry):

go
config := &flashdb.Config{Path: "", EvictionInterval: 10}
db, err := flashdb.New(config)

Transactions: Update for writes, View for reads

All data access goes through transactions: db.Update for read-write work (only one writer at a time) and db.View for read-only snapshots. When your callback returns nil, a write transaction commits; a non-nil error rolls back changes from that transaction.


String key-value example: set, get, delete

This golang key value database example stores a small map of students, reads one email, deletes Anna, then reads again. Save as main.go beside a go.mod that already requires FlashDB.

Important detail when looping: call tx.Set for every key—return only when an error occurs, not inside the loop on the first key.

go
package main

import (
	"errors"
	"fmt"
	"log"

	"github.com/arriqaaq/flashdb"
)

func main() {
	config := &flashdb.Config{Path: "", EvictionInterval: 10}
	db, err := flashdb.New(config)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	studentMap := map[string]string{
		"Anna":   "[email protected]",
		"Bob":    "[email protected]",
		"Cloe":   "[email protected]",
		"Daniel": "[email protected]",
	}

	err = db.Update(func(tx *flashdb.Tx) error {
		for key, value := range studentMap {
			if err := tx.Set(key, value); err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

	err = db.View(func(tx *flashdb.Tx) error {
		val, err := tx.Get("Anna")
		if err != nil {
			return err
		}
		fmt.Printf("value is %s\n", val)
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

	err = db.Update(func(tx *flashdb.Tx) error {
		return tx.Delete("Anna")
	})
	if err != nil {
		log.Fatal(err)
	}

	err = db.View(func(tx *flashdb.Tx) error {
		_, err := tx.Get("Anna")
		if err != nil {
			if errors.Is(err, flashdb.ErrInvalidKey) {
				fmt.Println("Anna: key missing after delete")
			} else {
				return err
			}
		}
		val2, err := tx.Get("Bob")
		if err != nil {
			return err
		}
		fmt.Printf("Bob: %s\n", val2)
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}
}

Example output from go run .:

text
value is [email protected]
Anna: key missing after delete
Bob: [email protected]

Summary

FlashDB gives you a go in memory database style API with optional append-only persistence when Path is non-empty—useful when you want golang in memory database speed plus restart durability. Work always happens inside Update or View transactions; string operations such as Set, Get, and Delete map cleanly to a golang key value workflow. Separate EvictionInterval (TTL sweeps) from NoSync (fsync trade-off). For another embedded in memory database golang option, see the memdb article.

String commands include SET, GET, DELETE, EXPIRE, TTL, and related helpers; hash, set, and sorted-set commands follow the Redis-like naming used in the upstream libraries—consult the FlashDB README for the full matrix.


References


Frequently Asked Questions

1. What is FlashDB?

FlashDB is an embedded key-value store written in Go that keeps primary data in memory and can optionally persist changes through an append-only log when you set a non-empty data directory.

2. Is FlashDB a golang in memory database?

Yes in the sense that working sets live in memory for fast reads and writes; when Config.Path is set it also replays and appends to on-disk log files for durability across restarts.

3. How is FlashDB different from Redis?

Redis is a separate server process and protocol; FlashDB is a Go library you link into your application with Update and View transactions rather than a network client.

4. How do I install FlashDB?

Create a module with go mod init, then run go get github.com/arriqaaq/flashdb (see the install section for a minimal go.mod example).

5. What does an empty `Config.Path` mean?

An empty path disables persistence so the database is memory-only for that process lifetime; non-empty paths enable append-only logging under that directory.

6. Why must writes use `db.Update`?

FlashDB allows many concurrent read transactions but serializes writes; Update runs your function inside a single read-write transaction that commits or rolls back as a unit.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise spanning these technologies, he develops …

  • Deep Learning with TensorFlow
  • Machine Learning with Python
  • Go (programming language)
  • Python (programming language)
  • Java (programming language)
  • MongoDB