Persistence for Go – without a line of SQL Open Source
ORM++ is our model-first persistence module for Go: you declare your models as structs with tags, ORM++ does the rest – from the schema through queries to event sourcing and migrations.
Declare models instead of programming the database
The approach is consistently model-first: a Go struct with tags describes what gets stored – tables, indexes, system tables and workers are derived from it. Whether a model is kept as a classic CRUD table or as an event-sourced aggregate with full history is a single registration decision.
Code example
import orm "gitlab.techeve.de/orm-plus-plus/orm-plus-plus"
type Todo struct {
ID orm.ID `orm:"pk"`
Title string `orm:"index"`
Done bool
}
db, err := orm.Open(orm.SQLite("./todo.db"))
orm.Register[Todo](db, orm.CRUD())
db.Migrate(ctx)
db.StartWorkers(ctx)
ctx = orm.WithTenant(ctx, orm.SingleTenant)
todos := orm.Repo[Todo](db)
todos.Insert(ctx, &Todo{Title: "ORM++ bauen"})
open, _ := todos.Query(ctx).Where(orm.Eq("Done", false)).All() What ORM++ does
CRUD and event sourcing – in one library
Classic create/read/update/delete models and event-driven aggregates live side by side in the same application: with CloudEvents, snapshots and archiving where history matters – and plain tables where it does not.
One codebase, three databases
The same application runs unchanged on SQLite, PostgreSQL and YugabyteDB. From the single-file prototype to the distributed cluster, nothing in the application code changes.
Multi-tenancy built in
Tenant and geo scoping are anchored structurally in the data model rather than bolted on afterwards: without a tenant context no query runs – data leaks between tenants become a compile-time matter.
Migrations without downtime
The old and the new model version run in parallel until everything is migrated – schema changes need no maintenance window and no big-bang rewrite.
Documentation & source
Introduction, quick start and examples are in the documentation – the code is in the project’s GitLab repository.