Skip to content

Low Memory Mode

Run NornicDB in resource-constrained environments like Docker containers, Raspberry Pi, or VMs with limited RAM.

Overview

NornicDB's Low Memory Mode reduces RAM usage by 50-70% compared to default settings, enabling deployment on systems with as little as 512MB of available memory. This is essential for:

  • Docker containers with default 2GB memory limits
  • Raspberry Pi and other ARM SBCs
  • Cloud VMs with limited RAM (t2.micro, etc.)
  • Development environments running multiple services
  • Edge deployments where resources are scarce

Quick Start

Environment Variable

# Enable low memory mode via environment variable
export NORNICDB_LOW_MEMORY=true
nornicdb serve

Docker

docker run -d \
  --name nornicdb \
  -p 7474:7474 \
  -p 7687:7687 \
  -e NORNICDB_LOW_MEMORY=true \
  timothyswt/nornicdb-arm64-metal:latest

Docker Compose

services:
  nornicdb:
    image: timothyswt/nornicdb-arm64-metal:latest
    environment:
      - NORNICDB_LOW_MEMORY=true
      - GOGC=100  # Recommended with low memory mode
    ports:
      - "7474:7474"
      - "7687:7687"
    volumes:
      - nornicdb-data:/data

Command Line Flag

nornicdb serve --low-memory

Memory Usage Comparison

Mode BadgerDB RAM Typical Total Use Case
High Performance (default) ~1GB 1.5-2GB Servers with 8GB+ RAM
Default ~150MB 300-500MB General purpose
Low Memory ~50MB 150-300MB Resource-constrained

Breakdown by Component

Component High Performance Default Low Memory
BadgerDB MemTable 128MB × 5 64MB × 3 8MB × 1
Value Log 256MB 128MB 32MB
Block Cache 256MB 128MB 8MB
Index Cache 128MB 64MB 4MB
Total Storage Layer ~1GB ~150MB ~50MB

Configuration Options

Environment Variables

Variable Type Default Description
NORNICDB_LOW_MEMORY bool false Enable low memory mode
NORNICDB_BADGER_HIGH_PERFORMANCE bool true High performance mode (mutually exclusive with low memory)
GOGC int 100 Go garbage collector target percentage

CLI Flags

nornicdb serve --help

Flags:
  --low-memory             Use minimal RAM (for resource constrained environments)
  --badger-high-performance Enable BadgerDB high performance mode (default true)
  --gc-percent             GC aggressiveness (100=default, lower=more aggressive)

Priority Order

  1. --low-memory flag overrides everything
  2. NORNICDB_LOW_MEMORY=true environment variable
  3. Default: Auto-detect based on available system memory (planned)

Performance Impact

Low memory mode trades some performance for reduced RAM usage:

Metric High Performance Low Memory Impact
Write throughput 50,000 ops/sec 20,000 ops/sec -60%
Read throughput 100,000 ops/sec 80,000 ops/sec -20%
Query latency (p50) 1ms 2ms +100%
Query latency (p99) 5ms 15ms +200%
Startup time 2s 1s -50%

Note: These numbers are approximate and vary by workload. For most use cases, low memory mode provides acceptable performance.

Docker Memory Limits

Docker Desktop defaults to 2GB memory. With NornicDB's high-performance mode + embedding model (~1.2GB), this can cause OOM kills.

Symptoms of OOM

# Container repeatedly restarts
docker ps
CONTAINER ID   STATUS                         PORTS
abc123         Restarting (137) 5 seconds ago

# Exit code 137 = SIGKILL (OOM)
docker logs nornicdb

Solution: Enable Low Memory Mode

# docker-compose.yml
services:
  nornicdb:
    image: timothyswt/nornicdb-arm64-metal:latest
    environment:
      - NORNICDB_LOW_MEMORY=true
      - GOGC=100
    # Optional: Set explicit memory limit
    deploy:
      resources:
        limits:
          memory: 1G

Alternative: Increase Docker Memory

# Docker Desktop: Settings > Resources > Memory > 4GB+

# Or use explicit limit
docker run --memory=4g nornicdb ...

Embedding Model Considerations

The embedded BGE-M3 model requires ~1.2GB RAM. In low memory mode:

  1. Use external embedding service (Ollama, OpenAI) instead of local model
  2. Or increase container memory to 2GB+
# Option 1: External embeddings (recommended for low memory)
services:
  nornicdb:
    environment:
      - NORNICDB_LOW_MEMORY=true
      - NORNICDB_EMBEDDING_PROVIDER=ollama
      - NORNICDB_EMBEDDING_URL=http://ollama:11434

  ollama:
    image: ollama/ollama:latest
    # Ollama manages its own memory
# Option 2: Local embeddings with more memory
services:
  nornicdb:
    environment:
      - NORNICDB_EMBEDDING_PROVIDER=local
    deploy:
      resources:
        limits:
          memory: 2.5G  # 1.2GB model + 1GB BadgerDB + headroom

WAL Compaction

Low memory mode works well with automatic WAL compaction to prevent disk bloat:

services:
  nornicdb:
    environment:
      - NORNICDB_LOW_MEMORY=true
      - NORNICDB_WAL_ENABLED=true
    volumes:
      - nornicdb-data:/data
      # WAL will auto-compact every 5 minutes
      # Snapshots stored in /data/snapshots

Manual WAL Cleanup

If your WAL has already grown large:

# Stop NornicDB
docker stop nornicdb

# Remove bloated WAL (data is safe in BadgerDB)
rm -f /path/to/data/wal/wal.log

# Restart with low memory mode
docker start nornicdb

Raspberry Pi Deployment

For Raspberry Pi 4 (2GB+ RAM):

# Use ARMv8 image with low memory mode
docker run -d \
  --name nornicdb \
  -p 7474:7474 \
  -p 7687:7687 \
  -e NORNICDB_LOW_MEMORY=true \
  -e NORNICDB_EMBEDDING_PROVIDER=ollama \
  -e GOGC=50 \
  -v nornicdb-data:/data \
  --restart unless-stopped \
  timothyswt/nornicdb-arm64:latest

For Raspberry Pi 3 (1GB RAM):

# Minimal configuration - disable local embeddings
docker run -d \
  --name nornicdb \
  -p 7474:7474 \
  -p 7687:7687 \
  -e NORNICDB_LOW_MEMORY=true \
  -e NORNICDB_EMBEDDING_ENABLED=false \
  -e GOGC=30 \
  -v nornicdb-data:/data \
  --restart unless-stopped \
  timothyswt/nornicdb-arm64:latest

Programmatic Configuration

Go API

import "github.com/orneryd/nornicdb/pkg/nornicdb"

config := nornicdb.DefaultConfig()
config.LowMemoryMode = true  // Enable low memory mode

db, err := nornicdb.Open("/data/nornicdb", config)
if err != nil {
    log.Fatal(err)
}
defer db.Close()

Storage Engine Options

import "github.com/orneryd/nornicdb/pkg/storage"

// Create low-memory BadgerDB engine
opts := storage.BadgerOptions{
    DataDir:   "/data/nornicdb",
    LowMemory: true,
}
engine, err := storage.NewBadgerEngineWithOptions(opts)

Monitoring Memory Usage

Container Stats

# Real-time memory usage
docker stats nornicdb

# One-time check
docker stats nornicdb --no-stream

NornicDB Metrics

# Memory metrics endpoint
curl http://localhost:7474/metrics | grep memory

# Key metrics:
# - go_memstats_alloc_bytes: Current allocations
# - go_memstats_sys_bytes: Total memory from OS
# - badger_lsm_size_bytes: LSM tree size
# - badger_vlog_size_bytes: Value log size

Health Check

# Check if NornicDB is healthy
curl http://localhost:7474/health

# Response includes memory info
{
  "status": "healthy",
  "memory": {
    "allocated": "45MB",
    "system": "120MB",
    "gc_pause_ns": 1234567
  }
}

Troubleshooting

Still Running Out of Memory

  1. Check actual usage:

    docker stats nornicdb --no-stream
    

  2. Lower GC target:

    # More aggressive garbage collection
    docker run -e GOGC=50 ...
    

  3. Disable features:

    # Disable local embeddings
    docker run -e NORNICDB_EMBEDDING_ENABLED=false ...
    

  4. Use swap (last resort):

    # Add swap to container (not recommended for production)
    docker run --memory=1g --memory-swap=2g ...
    

Performance Too Slow

Low memory mode prioritizes RAM over speed. If performance is unacceptable:

  1. Increase available memory and disable low memory mode
  2. Use SSD storage to compensate for reduced caching
  3. Optimize queries to reduce memory pressure
  4. Consider horizontal scaling with multiple instances

WAL Growing Despite Low Memory Mode

WAL growth is managed separately from memory mode. Ensure auto-compaction is enabled:

environment:
  - NORNICDB_WAL_ENABLED=true
  # WAL will auto-compact every 5 minutes

Best Practices

Do ✅

  • Use NORNICDB_LOW_MEMORY=true for containers with < 4GB RAM
  • Set GOGC=100 (or lower) alongside low memory mode
  • Use external embedding services (Ollama) instead of local models
  • Monitor memory usage with docker stats
  • Enable WAL auto-compaction

Don't ❌

  • Don't enable both LOW_MEMORY and HIGH_PERFORMANCE
  • Don't load large embedding models (>500MB) in low memory mode
  • Don't disable WAL compaction (causes disk bloat)
  • Don't set memory limits below 512MB

Memory issues?Troubleshooting Guide
Need more performance? → Consider upgrading to a system with 8GB+ RAM