dynamorm

package module
v1.0.23 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2025 License: Apache-2.0 Imports: 31 Imported by: 3

README

DynamORM - Type-Safe DynamoDB ORM for Go

Go Version License Documentation Go Report Card Coverage Status

DynamORM is a Lambda-native, type-safe ORM for Amazon DynamoDB written in Go. Designed specifically for serverless architectures, it provides lightweight wrappers around DynamoDB operations while maintaining compatibility with Infrastructure as Code patterns.

🎯 Project Vision

DynamoDB is an incredible database - it's fast, cheap, and scales fantastically. However, its verbose API and complex data structures make it challenging to work with. DynamORM aims to provide developers with an intuitive, Go-idiomatic interface for DynamoDB without sacrificing any of its power.

📚 Documentation

  • Design Document - Comprehensive overview of DynamORM's features and API design
  • Architecture - Technical architecture and implementation details
  • Roadmap - Detailed implementation plan and timeline
  • Comparison - Side-by-side comparison with raw DynamoDB SDK

✨ Key Features

  • 🚀 Lambda-Native: 11ms cold starts (91% faster than standard SDK)
  • 🔒 Type-Safe: Full Go type safety with compile-time checks
  • 🎯 Simple API: Write 80% less code than AWS SDK
  • High Performance: 20,000+ operations per second
  • 🧪 Testable: Interface-based design enables easy mocking (v1.0.1+)
  • 🌍 Multi-Account: Built-in cross-account support
  • 💰 Cost Efficient: Smart query optimization reduces DynamoDB costs
  • 🔄 Transactions: Full support for DynamoDB transactions
  • 📦 Batch Operations: Efficient batch read/write operations
  • 🎨 Clean API: Intuitive, chainable query interface
  • 🔁 Consistency Support: Built-in patterns for handling eventual consistency

🚀 Quick Start

Installation
go get github.com/dynamorm/dynamorm
Basic Usage
package main

import (
    "context"
    "log"
    "github.com/pay-theory/dynamorm"
    "github.com/pay-theory/dynamorm/pkg/session"
)

// Define your model
type User struct {
    ID        string `dynamorm:"pk"`
    Email     string `dynamorm:"sk"`
    Name      string
    CreatedAt int64  `dynamorm:"created_at"`
}

func main() {
    // Initialize DynamORM with proper configuration
    config := session.Config{
        Region: "us-east-1",
        // For local development:
        // Endpoint: "http://localhost:8000",
    }
    
    db, err := dynamorm.New(config)
    if err != nil {
        log.Fatal("Failed to initialize DynamORM:", err)
    }

    // Create a user
    user := &User{
        ID:    "user123",
        Email: "john@example.com",
        Name:  "John Doe",
    }
    
    err = db.Model(user).Create()
    if err != nil {
        log.Printf("Create error: %v", err)
    }
    
    // Query users
    var users []User
    err = db.Model(&User{}).
        Where("ID", "=", "user123").
        All(&users)
    if err != nil {
        log.Printf("Query error: %v", err)
    }
}

📊 Performance

DynamORM is optimized for Lambda environments with impressive performance metrics:

Metric DynamORM AWS SDK Improvement
Cold Start 11ms 127ms 91% faster
Memory Usage 18MB 42MB 57% less
Operations/sec 20,000+ 12,000 67% more

🎯 Core Features

Type-Safe Operations
// Compile-time type checking
var user User
err := db.Model(&User{}).
    Where("ID", "=", "123").
    First(&user)
🧪 Testable Design (v1.0.1+)

DynamORM uses interfaces and provides pre-built mocks (v1.0.2+), making it easy to test:

// In your service
import "github.com/pay-theory/dynamorm/pkg/core"

type UserService struct {
    db core.DB  // Use interface instead of concrete type
}

func NewUserService(db core.DB) *UserService {
    return &UserService{db: db}
}

// In your tests - no DynamoDB required!
import (
    "testing"
    "github.com/pay-theory/dynamorm/pkg/mocks"
    "github.com/stretchr/testify/mock"
)

func TestUserService(t *testing.T) {
    mockDB := new(mocks.MockDB)
    mockQuery := new(mocks.MockQuery)
    
    mockDB.On("Model", &User{}).Return(mockQuery)
    mockQuery.On("Where", "ID", "=", "123").Return(mockQuery)
    mockQuery.On("First", mock.Anything).Return(nil)
    
    service := NewUserService(mockDB)
    // Test your service logic without DynamoDB
}

See our Testing Guide for complete examples.

Smart Query Builder
// Automatic index selection
var results []User
err := db.Model(&User{}).
    Index("email-index").
    Where("Email", "=", "john@example.com").
    OrderBy("CreatedAt", "DESC").
    Limit(10).
    All(&results)
Transaction Support
err := db.Transaction(func(tx *dynamorm.Tx) error {
    // All operations in transaction
    user.Balance -= 100
    if err := tx.Model(user).Update(); err != nil {
        return err
    }
    
    transfer := &Transfer{Amount: 100}
    return tx.Model(transfer).Create()
})
Multi-Account Support
// Easy cross-account operations
db := dynamorm.New(
    dynamorm.WithMultiAccount(map[string]string{
        "prod": "arn:aws:iam::111111:role/dynamodb-role",
        "dev":  "arn:aws:iam::222222:role/dynamodb-role",
    }),
)

// Use specific account
err := db.WithAccount("prod").Model(&User{}).All(&users)
Consistency Patterns

DynamORM provides built-in support for handling DynamoDB's eventual consistency:

// Strongly consistent reads on main table
err := db.Model(&User{}).
    Where("ID", "=", "user123").
    ConsistentRead().
    First(&user)

// Retry for GSI eventual consistency
err := db.Model(&User{}).
    Index("email-index").
    Where("Email", "=", "user@example.com").
    WithRetry(5, 100*time.Millisecond).
    First(&user)

// Advanced read-after-write patterns
helper := consistency.NewReadAfterWriteHelper(db)
err := helper.CreateWithConsistency(user, &consistency.WriteOptions{
    VerifyWrite:           true,
    WaitForGSIPropagation: 500*time.Millisecond,
})

See the Consistency Patterns Guide for detailed examples.

Table Operations

DynamORM provides simple table operations for development and testing:

// Create table from model (development/testing)
err := db.CreateTable(&User{})

// Ensure table exists (idempotent)
err := db.EnsureTable(&User{})

// AutoMigrate with data copy
err := db.AutoMigrateWithOptions(&UserV1{},
    dynamorm.WithTargetModel(&UserV2{}),
    dynamorm.WithDataCopy(true),
    dynamorm.WithTransform(transformFunc),
)
📚 Documentation

🏗️ Examples

Check out our examples directory for real-world usage:

🤝 Contributing

We love contributions! Please see our Contributing Guide for details.

Quick Contribution Guide
  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📋 Requirements

  • Go 1.21 or higher
  • AWS credentials configured
  • DynamoDB tables created

🧪 Testing

# Run all tests
make test

# Run with coverage
make test-coverage

# Run integration tests
make test-integration

🚀 Lambda Deployment

DynamORM is optimized for Lambda:

package main

import (
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/dynamorm/dynamorm"
)

var db *dynamorm.DB

func init() {
    // Initialize once, reuse across invocations
    db = dynamorm.New(dynamorm.WithLambdaOptimizations())
}

func handler(ctx context.Context, event Event) error {
    // Your handler code
    return db.Model(&User{}).Create()
}

func main() {
    lambda.Start(handler)
}

💬 Community

📈 Roadmap

See our public roadmap for upcoming features:

  • GraphQL integration
  • Real-time subscriptions
  • Enhanced data transformation utilities
  • Admin UI
  • More database adapters

🏆 Used By

DynamORM is trusted by companies processing millions of requests:

  • Pay Theory - Payment processing platform
  • Your Company Here - Let us know!

📄 License

DynamORM is licensed under the Apache License 2.0.

🙏 Acknowledgments

Special thanks to all our contributors and the Go community!


Made with ❤️ by the DynamORM team

Documentation

Overview

Package dynamorm provides a type-safe ORM for Amazon DynamoDB in Go

lambda.go

multiaccount.go

Index

Constants

This section is empty.

Variables

View Source
var (
	WithBackupTable = schema.WithBackupTable
	WithDataCopy    = schema.WithDataCopy
	WithTargetModel = schema.WithTargetModel
	WithTransform   = schema.WithTransform
	WithBatchSize   = schema.WithBatchSize
)

Re-export AutoMigrate options for convenience

Functions

func EnableXRayTracing

func EnableXRayTracing() bool

EnableXRayTracing enables AWS X-Ray tracing for DynamoDB calls

func GetLambdaMemoryMB

func GetLambdaMemoryMB() int

GetLambdaMemoryMB returns the allocated memory in MB

func GetPartnerFromContext

func GetPartnerFromContext(ctx context.Context) string

GetPartnerFromContext retrieves partner ID from context

func GetRemainingTimeMillis

func GetRemainingTimeMillis(ctx context.Context) int64

GetRemainingTimeMillis returns milliseconds until Lambda timeout

func IsLambdaEnvironment

func IsLambdaEnvironment() bool

IsLambdaEnvironment detects if running in AWS Lambda

func New

func New(config session.Config) (core.ExtendedDB, error)

New creates a new DynamORM instance with the given configuration

func NewBasic added in v1.0.1

func NewBasic(config session.Config) (core.DB, error)

NewBasic creates a new DynamORM instance that returns the basic DB interface Use this when you only need core functionality and want easier mocking

func PartnerContext

func PartnerContext(ctx context.Context, partnerID string) context.Context

PartnerContext adds partner information to context for tracing

Types

type AccountConfig

type AccountConfig struct {
	RoleARN    string
	ExternalID string
	Region     string
	// Optional: Custom session duration (default is 1 hour)
	SessionDuration time.Duration
}

AccountConfig holds configuration for a partner account

type AutoMigrateOption

type AutoMigrateOption = schema.AutoMigrateOption

Re-export types for convenience

type ColdStartMetrics

type ColdStartMetrics struct {
	TotalDuration time.Duration
	Phases        map[string]time.Duration
	MemoryMB      int
	IsLambda      bool
}

ColdStartMetrics contains cold start performance data

func BenchmarkColdStart

func BenchmarkColdStart(models ...any) ColdStartMetrics

BenchmarkColdStart measures cold start performance

func (ColdStartMetrics) String

func (m ColdStartMetrics) String() string

String returns a formatted string of the metrics

type Config

type Config = session.Config

Re-export types for convenience

type DB

type DB struct {
	// contains filtered or unexported fields
}

DB is the main DynamORM database instance

func (*DB) AutoMigrate

func (db *DB) AutoMigrate(models ...any) error

AutoMigrate creates or updates tables based on the given models

func (*DB) AutoMigrateWithOptions

func (db *DB) AutoMigrateWithOptions(model any, opts ...any) error

AutoMigrateWithOptions performs enhanced auto-migration with data copy support

func (*DB) Close

func (db *DB) Close() error

Close closes the database connection

func (*DB) CreateTable

func (db *DB) CreateTable(model any, opts ...any) error

CreateTable creates a DynamoDB table for the given model

func (*DB) DeleteTable

func (db *DB) DeleteTable(model any) error

DeleteTable deletes the DynamoDB table for the given model

func (*DB) DescribeTable

func (db *DB) DescribeTable(model any) (any, error)

DescribeTable returns the table description for the given model

func (*DB) EnsureTable

func (db *DB) EnsureTable(model any) error

EnsureTable checks if a table exists for the model and creates it if not

func (*DB) Migrate

func (db *DB) Migrate() error

Migrate runs all pending migrations

func (*DB) Model

func (db *DB) Model(model any) core.Query

Model returns a new query builder for the given model

func (*DB) Transaction

func (db *DB) Transaction(fn func(tx *core.Tx) error) error

Transaction executes a function within a database transaction

func (*DB) TransactionFunc

func (db *DB) TransactionFunc(fn func(tx any) error) error

TransactionFunc executes a function within a database transaction This is the actual implementation that uses our sophisticated transaction support

func (*DB) WithContext

func (db *DB) WithContext(ctx context.Context) core.DB

WithContext returns a new DB instance with the given context

func (*DB) WithLambdaTimeout

func (db *DB) WithLambdaTimeout(ctx context.Context) core.DB

WithLambdaTimeout sets a deadline based on Lambda context

func (*DB) WithLambdaTimeoutBuffer

func (db *DB) WithLambdaTimeoutBuffer(buffer time.Duration) core.DB

WithLambdaTimeoutBuffer sets a custom timeout buffer for Lambda execution

type LambdaDB

type LambdaDB struct {
	core.ExtendedDB
	// contains filtered or unexported fields
}

LambdaDB wraps DB with Lambda-specific optimizations

func LambdaInit

func LambdaInit(models ...any) (*LambdaDB, error)

LambdaInit should be called in the init() function of your Lambda handler It performs one-time initialization to reduce cold start latency

func NewLambdaOptimized

func NewLambdaOptimized() (*LambdaDB, error)

NewLambdaOptimized creates a Lambda-optimized DB instance

func (*LambdaDB) GetMemoryStats

func (ldb *LambdaDB) GetMemoryStats() LambdaMemoryStats

GetMemoryStats returns current memory usage statistics

func (*LambdaDB) IsModelRegistered

func (ldb *LambdaDB) IsModelRegistered(model any) bool

IsModelRegistered checks if a model is already registered

func (*LambdaDB) OptimizeForColdStart

func (ldb *LambdaDB) OptimizeForColdStart()

OptimizeForColdStart reduces Lambda cold start time

func (*LambdaDB) OptimizeForMemory

func (ldb *LambdaDB) OptimizeForMemory()

OptimizeForMemory adjusts internal buffers based on available Lambda memory

func (*LambdaDB) PreRegisterModels

func (ldb *LambdaDB) PreRegisterModels(models ...any) error

PreRegisterModels registers models at init time to reduce cold starts

func (*LambdaDB) WithLambdaTimeout

func (ldb *LambdaDB) WithLambdaTimeout(ctx context.Context) *LambdaDB

WithLambdaTimeout creates a new DB instance with Lambda timeout handling

type LambdaMemoryStats

type LambdaMemoryStats struct {
	Alloc          uint64  // Bytes allocated and still in use
	TotalAlloc     uint64  // Bytes allocated (even if freed)
	Sys            uint64  // Bytes obtained from system
	NumGC          uint32  // Number of GC cycles
	AllocatedMB    float64 // MB currently allocated
	SystemMB       float64 // MB obtained from system
	LambdaMemoryMB int     // Total Lambda memory allocation
	MemoryPercent  float64 // Percentage of Lambda memory used
}

LambdaMemoryStats contains memory usage information

type MultiAccountDB

type MultiAccountDB struct {
	// contains filtered or unexported fields
}

MultiAccountDB manages DynamoDB connections across multiple AWS accounts

func NewMultiAccount

func NewMultiAccount(accounts map[string]AccountConfig) (*MultiAccountDB, error)

NewMultiAccount creates a multi-account aware DB

func (*MultiAccountDB) AddPartner

func (mdb *MultiAccountDB) AddPartner(partnerID string, config AccountConfig)

AddPartner dynamically adds a new partner configuration

func (*MultiAccountDB) Close

func (mdb *MultiAccountDB) Close() error

Close stops the refresh routine and cleans up

func (*MultiAccountDB) Partner

func (mdb *MultiAccountDB) Partner(partnerID string) (*LambdaDB, error)

Partner returns a DB instance for the specified partner account

func (*MultiAccountDB) RemovePartner

func (mdb *MultiAccountDB) RemovePartner(partnerID string)

RemovePartner removes a partner and clears its cached connection

func (*MultiAccountDB) WithContext

func (mdb *MultiAccountDB) WithContext(ctx context.Context) *MultiAccountDB

WithContext returns a new MultiAccountDB with the given context

Directories

Path Synopsis
Package examples demonstrates DynamORM's embedded struct support
Package examples demonstrates DynamORM's embedded struct support
initialization command
Package main demonstrates proper DynamORM initialization patterns to avoid nil pointer dereference errors
Package main demonstrates proper DynamORM initialization patterns to avoid nil pointer dereference errors
lambda command
optimization command
internal
pkg
consistency
Package consistency provides utilities for handling eventual consistency in DynamoDB
Package consistency provides utilities for handling eventual consistency in DynamoDB
core
Package core defines the core interfaces and types for DynamORM
Package core defines the core interfaces and types for DynamORM
errors
Package errors defines error types and utilities for DynamORM
Package errors defines error types and utilities for DynamORM
interfaces
Package interfaces provides abstractions for AWS SDK operations to enable mocking
Package interfaces provides abstractions for AWS SDK operations to enable mocking
marshal
Package marshal provides optimized marshaling for DynamoDB
Package marshal provides optimized marshaling for DynamoDB
mocks
Package mocks provides mock implementations for DynamORM interfaces and AWS SDK operations
Package mocks provides mock implementations for DynamORM interfaces and AWS SDK operations
model
Package model provides model registration and metadata management for DynamORM
Package model provides model registration and metadata management for DynamORM
query
Package query provides aggregate functionality for DynamoDB queries
Package query provides aggregate functionality for DynamoDB queries
session
Package session provides AWS session management and DynamoDB client configuration
Package session provides AWS session management and DynamoDB client configuration
testing
Package testing provides utilities for testing applications that use DynamORM.
Package testing provides utilities for testing applications that use DynamORM.
transaction
Package transaction provides atomic transaction support for DynamORM
Package transaction provides atomic transaction support for DynamORM
types
Package types provides type conversion between Go types and DynamoDB AttributeValues
Package types provides type conversion between Go types and DynamoDB AttributeValues

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL