Putnami
DocsGitHub

Licensed under FSL-1.1-MIT

Getting Started
Concepts
How To
Build A Web App
Build An Api Service
Share Code Between Projects
Configure Your App
Add Persistence
Add Authentication
Add Background Jobs
Principles
Tooling & Workspace
Workspace Overview
Cli
Jobs & Commands
SDK
Error Handling
Extensions
Typescript
Go
Python
Docker
Ci
Frameworks
Typescript
OverviewWebReact RoutingForms And ActionsStatic FilesApiErrors And ResponsesConfigurationLoggingHttp And MiddlewareDependency InjectionPlugins And LifecycleSessionsAuthPersistenceEventsStorageCachingWebsocketsTestingHealth ChecksTelemetryProto GrpcSmart Client
Go
OverviewHttpDependency InjectionPlugins And LifecycleConfigurationSecurityPersistenceErrorsEventsStorageCachingLoggingTelemetryGrpcService ClientsValidationOpenapiTesting
Platform
  1. DocsSeparator
  2. FrameworksSeparator
  3. GoSeparator
  4. Caching

Caching

go.putnami.dev/cache provides a generic caching layer with in-memory, disk, and layered implementations. All caches are safe for concurrent use.

Cache interface

All implementations share the same interface:

type Cache interface {
    Get(ctx context.Context, key string) ([]byte, bool)
    Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
    Delete(ctx context.Context, key string) error
    Has(ctx context.Context, key string) bool
    Clear(ctx context.Context) error
    Close() error
}

Memory cache

In-memory cache with optional FIFO eviction:

import "go.putnami.dev/cache"

c := cache.NewMemoryCache(cache.MemoryConfig{
    MaxEntries:      1000,           // 0 = unlimited
    CleanupInterval: 5 * time.Minute,
})
defer c.Close()

Configuration

Field Type Default Description
MaxEntries int 0 Maximum entries (0 = unlimited). FIFO eviction when exceeded
CleanupInterval time.Duration — Interval for removing expired entries

Disk cache

Filesystem-backed persistent cache that survives process restarts:

c, err := cache.NewDiskCache(cache.DiskConfig{
    Dir:             "./cache",
    CleanupInterval: 10 * time.Minute,
})
if err != nil {
    log.Fatal(err)
}
defer c.Close()

Objects are stored as files with SHA-256 hashed filenames. The directory is created automatically if it doesn't exist.

Configuration

Field Type Default Description
Dir string — Cache directory (created if needed)
CleanupInterval time.Duration — Interval for removing expired entries

Layered cache

Compose an L1/L2 cache hierarchy. On a cache miss in L1, the value is fetched from L2 and promoted to L1:

memory := cache.NewMemoryCache(cache.MemoryConfig{MaxEntries: 100})
disk, _ := cache.NewDiskCache(cache.DiskConfig{Dir: "./cache"})

c := cache.NewLayeredCache(memory, disk)
defer c.Close()

Behavior

Operation L1 (memory) L2 (disk)
Get Check first; on miss, fetch from L2 and promote Checked on L1 miss
Set Write Write
Delete Delete Delete
Clear Clear Clear

Operations

Set and get

// Store with TTL
err := c.Set(ctx, "user:123", []byte(`{"name":"Jane"}`), 5*time.Minute)

// Store without expiration
err := c.Set(ctx, "config", data, 0)

// Retrieve
value, found := c.Get(ctx, "user:123")
if !found {
    // cache miss or expired
}

Check and delete

if c.Has(ctx, "user:123") {
    // key exists and is not expired
}

err := c.Delete(ctx, "user:123")

// Clear all entries
err := c.Clear(ctx)

Patterns

Cache-aside

func (s *UserService) GetUser(ctx context.Context, id string) (*User, error) {
    key := "user:" + id

    // Check cache
    if data, found := s.cache.Get(ctx, key); found {
        var user User
        json.Unmarshal(data, &user)
        return &user, nil
    }

    // Cache miss — fetch from database
    user, err := s.repo.FindByID(ctx, "id", id)
    if err != nil {
        return nil, err
    }

    // Store in cache
    data, _ := json.Marshal(user)
    s.cache.Set(ctx, key, data, 10*time.Minute)

    return &user, nil
}

Cache invalidation

func (s *UserService) UpdateUser(ctx context.Context, id string, input UpdateInput) error {
    if err := s.repo.Update(ctx, id, input); err != nil {
        return err
    }
    // Invalidate cached entry
    return s.cache.Delete(ctx, "user:"+id)
}

Related guides

  • Persistence — database queries to cache
  • Configuration — cache configuration

On this page

  • Caching
  • Cache interface
  • Memory cache
  • Configuration
  • Disk cache
  • Configuration
  • Layered cache
  • Behavior
  • Operations
  • Set and get
  • Check and delete
  • Patterns
  • Cache-aside
  • Cache invalidation
  • Related guides