Skip to main content

In-Memory Targets

Laredo provides two in-memory target types for different use cases.

Indexed In-Memory

A schema-agnostic in-memory table replica with configurable secondary indexes. Stores raw Row maps.

Configuration

targets = [{
type = indexed-memory
lookup_fields = [instance_id, key]
additional_indexes = [
{ name = by_instance, fields = [instance_id], unique = false }
{ name = by_key_version, fields = [key, version], unique = true }
]
}]

Library usage

target := memory.NewIndexedTarget(
memory.LookupFields("instance_id", "key"),
memory.AddIndex(laredo.IndexDefinition{Name: "by_instance", Fields: []string{"instance_id"}}),
)

Query API

// Lookup by primary index (unique)
row, ok := target.Lookup("inst_abc", "settings/default")

// Lookup by named index (non-unique)
rows := target.LookupAll("by_instance", "inst_abc")

// Get by primary key
row, ok := target.Get(42)

// All rows (returns iter.Seq2[string, Row])
for key, row := range target.All() {
fmt.Printf("pk=%s: %v\n", key, row)
}

// Row count
count := target.Count()

// Subscribe to changes
unsubscribe := target.Listen(func(old, new laredo.Row) {
// old is nil on insert, new is nil on delete
})

Compiled In-Memory

Deserializes each row into a strongly-typed domain object via a pluggable compiler function.

Configuration

targets = [{
type = compiled-memory
compiler = ruleset
key_fields = [instance_id, key]
filter {
field = key
prefix = "rulesets/"
}
}]

Library usage

target := memory.NewCompiledTarget(
memory.Compiler(func(row laredo.Row) (any, error) {
return parseRuleset(row)
}),
memory.KeyFields("instance_id", "key"),
)

Query API

// Lookup by key fields
obj, ok := target.Get("inst_abc", "rulesets/default")

// All compiled objects (returns iter.Seq2[string, any])
for key, obj := range target.All() {
fmt.Printf("pk=%s: %v\n", key, obj)
}

// Row count
count := target.Count()

// Subscribe to changes (old/new are compiled domain objects)
unsubscribe := target.Listen(func(old, new any) {
// old is nil on insert, new is nil on delete
})

Schema changes

Both in-memory targets default to RE_BASELINE on schema changes — the safest option. If your application can handle schema evolution, implement a custom target.

Thread safety

Both targets are safe for concurrent reads during streaming. The engine writes from a single goroutine; reads are protected by sync.RWMutex.