Skip to main content

Firebase RTDB Adapter

goclarc module settings --db rtdb --schema schemas/settings.yaml

What Gets Generated

internal/modules/settings/repository.go ← Firebase RTDB implementation

Repository Pattern

The generated repository uses firebase-admin-go/v4:

type repository struct {
ref *db.Ref
}

func NewRepository(client *db.Client) Repository {
return &repository{ref: client.NewRef("settings")}
}

func (r *repository) GetByID(ctx context.Context, id string) (*Entity, error) {
var data map[string]interface{}
if err := r.ref.Child(id).Get(ctx, &data); err != nil {
return nil, fmt.Errorf("settings.repository.GetByID: %w", err)
}
if data == nil {
return nil, fmt.Errorf("settings not found")
}
return mapToEntity(data, id), nil
}

Key Differences from Relational Adapters

FeaturePostgres / MongoDBFirebase RTDB
Primary key typestring (UUID or ObjectID hex)RTDB Push() key
Timestampstime.Time / RFC3339int64 unix milliseconds
JSON fieldsjson.RawMessage / bson.Mmap[string]interface{}
CreateINSERT / InsertOneref.Push()
ListSELECT * / Findref.Get() → map iteration
UpdateUPDATE / FindOneAndUpdateref.Child(id).Update()

Timestamps as Unix Milliseconds

RTDB stores timestamps as int64 (milliseconds since epoch). There is no time.Time conversion — the View type is also int64:

// Schema: type: timestamp
// Entity
CreatedAt int64

// View
CreatedAt int64

To display as a human-readable date, convert on the client side.

mapToEntity Conversion

RTDB returns map[string]interface{} from reads. The generated converter type-asserts each field:

func mapToEntity(data map[string]interface{}, id string) *Entity {
e := &Entity{}
e.ID = id
if v, ok := data["email"]; ok && v != nil {
if cast, ok := v.(string); ok {
e.Email = cast
}
}
// ...
return e
}

Required Imports

import "firebase.google.com/go/v4/db"
go get firebase.google.com/go/v4

Connection Setup

app, err := firebase.NewApp(ctx, nil)
if err != nil {
logger.Fatal("firebase init", zap.Error(err))
}
dbClient, err := app.DatabaseWithURL(ctx, cfg.FirebaseDBURL)
if err != nil {
logger.Fatal("firebase db", zap.Error(err))
}

settingsRepo := settings.NewRepository(dbClient)
settingsService := settings.NewService(settingsRepo)
settingsHandler := settings.NewHandler(settingsService)
settings.RegisterRoutes(v1, settingsHandler, middleware.Auth())

Firebase authentication is handled via Application Default Credentials (ADC) — set GOOGLE_APPLICATION_CREDENTIALS in your environment.