FluxaORM v2: Code-Generation-Based Go ORM for MySQL and Redis
Guide
GitHub
Guide
GitHub
    • Introduction
    • Registry
    • Data Pools
    • Entities
    • Entity Fields
    • MySQL Indexes
    • Code Generation
    • Engine
    • Context
    • Entity Schema
    • Schema Update
    • CRUD Operations
    • Async Flush
    • Search
    • Redis Search
    • MySQL Queries
    • Local Cache
    • Context Cache
    • Fake Delete
    • Entity Lifecycle Callbacks
    • Metrics
    • Redis Operations
    • Distributed Lock
    • Event Broker
    • Dirty Streams
    • Queries Log
    • Testing

Introduction

FluxaORM is a code-generation-first ORM for Go, purpose-built for MySQL and Redis. Instead of relying on runtime reflection to map structs to database rows, FluxaORM generates fully typed Go code from your entity definitions — giving you compile-time safety, zero-reflection data access, and built-in dirty tracking.

How It Works

The FluxaORM workflow has four steps:

  1. Define entity structs with orm: struct tags
  2. Register entities and connection pools in a Registry
  3. Validate the registry to produce an Engine, then call Generate() to emit typed Go code
  4. Use the generated Provider and Entity types in your application
package main

import (
    "context"
    "fmt"

    "github.com/latolukasz/fluxaorm/v2"
)

// Step 1: Define your entity struct
type UserEntity struct {
    ID    uint64 `orm:"redisCache"`
    Name  string `orm:"required"`
    Email string `orm:"unique=Email;required"`
    Age   uint8
}

func main() {
    // Step 2: Register entities and pools
    registry := fluxaorm.NewRegistry()
    registry.RegisterMySQL("root:root@tcp(localhost:3306)/app", fluxaorm.DefaultPoolCode, nil)
    registry.RegisterRedis("localhost:6379", 0, fluxaorm.DefaultPoolCode, nil)
    registry.RegisterLocalCache(fluxaorm.DefaultPoolCode, 100000)
    registry.RegisterEntity(&UserEntity{})

    // Step 3: Validate and generate
    engine, err := registry.Validate()
    if err != nil {
        panic(err)
    }
    err = fluxaorm.Generate(engine, "./entities")
    if err != nil {
        panic(err)
    }
}

After running this program, the ./entities directory will contain generated code including a UserEntityProvider and a UserEntity type with typed getters and setters.

Using Generated Code

package main

import (
    "context"
    "fmt"

    "github.com/latolukasz/fluxaorm/v2"
    "myapp/entities"
)

func main() {
    // ... registry setup and validation as above ...
    ctx := engine.NewContext(context.Background())

    // Create a new entity
    user := entities.UserEntityProvider.New(ctx)
    user.SetName("Alice")
    user.SetEmail("alice@example.com")
    user.SetAge(30)
    err := ctx.Flush()
    if err != nil {
        panic(err)
    }

    // Fetch by ID
    user, found, err := entities.UserEntityProvider.GetByID(ctx, 1)
    if err != nil {
        panic(err)
    }
    if found {
        fmt.Println(user.GetName())  // "Alice"
        fmt.Println(user.GetAge())   // 30
    }

    // Search with WHERE clause
    users, err := entities.UserEntityProvider.Search(
        ctx,
        fluxaorm.NewWhere("`Age` >= ?", 18),
        nil,
    )
    if err != nil {
        panic(err)
    }
    for _, u := range users {
        fmt.Println(u.GetName(), u.GetEmail())
    }
}

Designed for MySQL

Unlike generic ORM libraries that abstract away database differences behind a lowest-common-denominator interface, FluxaORM is specifically tailored for MySQL. This allows it to take full advantage of MySQL-specific features, optimizations, and DDL semantics — including automatic schema migrations, proper ENUM/SET types, and efficient connection pool management based on your server's max_connections and wait_timeout settings.

Three-Tier Caching

FluxaORM provides a transparent, three-tier caching system for entity reads:

  1. Context cache — a per-request in-memory cache with a configurable TTL (default: 1 second). Populated automatically by GetByID and GetByIDs. Zero configuration required.
  2. Local cache — a per-process LRU cache stored in application memory. Configured per pool with a maximum key count.
  3. Redis cache — entities are serialized into Redis Lists, enabling fast lookups that bypass MySQL entirely. Enabled per entity with the orm:"redisCache" struct tag.

When an entity is requested, FluxaORM checks each tier in order and only falls through to MySQL when no cached copy is available. Cache invalidation is handled automatically when entities are modified and flushed.

Redis Search

Entities can opt in to Redis Search indexing via struct tags. The ORM automatically maintains Redis hash documents and FT.SEARCH indexes, enabling full-text and numeric queries that run entirely in Redis.

Dirty Tracking and Flush

Generated entity setters compare new values against the original database values and only mark changed fields as dirty. When you call ctx.Flush(), FluxaORM batches all pending INSERT, UPDATE, and DELETE operations into efficient SQL statements and updates Redis caches in a single pass.

For non-critical writes, ctx.FlushAsync(true) publishes SQL operations to a Redis Stream for asynchronous processing while updating cache immediately, and ctx.FlushAsync(false) defers both SQL and cache updates to the consumer.

Built-in Redis Client

FluxaORM includes its own Redis client with support for all standard commands plus additional features like distributed locks and rate limiters. No external Redis client library is needed.

Requirements

FluxaORM requires Redis 8.2 or later. The Validate() method will return an error if any registered Redis pool is running an older version.

What's Next

Continue to the Registry page to learn how to configure connection pools and register entities, or jump to Data Pools for details on MySQL, Redis, and local cache pool options.

Edit this page
Last Updated: 3/2/26, 1:49 PM
Next
Registry