NornicDB Plugin System

December 3, 2025 ยท View on GitHub

NornicDB features a powerful plugin system that extends Cypher with APOC (Awesome Procedures On Cypher) functions. The APOC plugin provides 964 functions covering collections, text processing, math, graph algorithms, data import/export, and more.

Overview

The plugin system provides:

  • Dynamic Plugin Loading: Plugins are .so files loaded automatically at startup
  • APOC Plugin: Pre-built plugin with 964 functions included in all Docker images
  • Custom Plugins: Create your own plugins following the same interface
  • Configuration Control: Enable/disable via environment variables

Quick Start

Using APOC Functions

All Docker images include the APOC plugin pre-loaded:

// Collection functions
RETURN apoc.coll.sum([1, 2, 3, 4, 5])           // 15
RETURN apoc.coll.avg([1, 2, 3, 4, 5])           // 3.0
RETURN apoc.coll.flatten([[1,2], [3,4]])        // [1,2,3,4]

// Text functions
RETURN apoc.text.capitalize('hello world')      // "Hello world"
RETURN apoc.text.camelCase('hello_world')       // "helloWorld"
RETURN apoc.text.levenshteinDistance('cat', 'bat')  // 1

// Math functions
RETURN apoc.math.sqrt(16)                       // 4.0
RETURN apoc.math.sigmoid(0)                     // 0.5

// Scoring functions
RETURN apoc.scoring.cosine([1,0], [0,1])        // 0.0
RETURN apoc.scoring.jaccard([1,2,3], [2,3,4])   // 0.5

// Spatial functions
RETURN apoc.spatial.haversineDistance(40.7128, -74.0060, 34.0522, -118.2437)

// Create functions
RETURN apoc.create.uuid()                       // "550e8400-e29b-41d4-..."

Configuration

Environment Variables

# Directory containing .so plugin files (default: /app/plugins in Docker)
NORNICDB_PLUGINS_DIR=/app/plugins

# Enable/disable plugin system
NORNICDB_PLUGINS_ENABLED=true

Docker Compose

services:
  nornicdb:
    image: timothyswt/nornicdb-arm64-metal:latest
    environment:
      - NORNICDB_PLUGINS_DIR=/app/plugins
    volumes:
      - ./custom-plugins:/app/plugins/custom  # Add custom plugins

Available Function Categories

The APOC plugin includes 964 functions across these categories:

CategoryCountDescription
apoc.coll46Collection operations (sum, avg, sort, flatten, union, etc.)
apoc.text41Text manipulation (capitalize, replace, distance, regex, etc.)
apoc.math45Mathematical operations (sqrt, trig, statistics, etc.)
apoc.convert24Type conversion (toFloat, toJson, toList, etc.)
apoc.date15Date/time handling (format, parse, add, etc.)
apoc.json18JSON operations (parse, stringify, path, merge, etc.)
apoc.util38Utilities (md5, sha256, uuid, compress, etc.)
apoc.agg15Aggregation (median, percentile, stdev, histogram, etc.)
apoc.algo9Graph algorithms (pageRank, dijkstra, etc.)
apoc.map25Map operations (merge, flatten, groupBy, etc.)
apoc.create19Node/relationship creation (node, relationship, uuid, etc.)
apoc.export14Data export (json, csv, cypher, graphML, etc.)
apoc.import19Data import (json, csv, xml, etc.)
apoc.load29Data loading (json, csv, jdbc, s3, kafka, etc.)
apoc.log25Logging (info, debug, warn, metrics, etc.)
apoc.node34Node operations (degree, labels, properties, etc.)
apoc.nodes22Multi-node operations (group, partition, connected, etc.)
apoc.rel29Relationship operations (type, properties, weight, etc.)
apoc.refactor20Graph refactoring (mergeNodes, renameLabel, etc.)
apoc.schema30Schema operations (indexes, constraints, etc.)
apoc.meta38Metadata (schema, stats, types, etc.)
apoc.neighbors6Neighbor traversal (atHop, bfs, dfs, etc.)
apoc.path9Path operations (expand, slice, etc.)
apoc.paths21Path finding (shortest, all, kShortest, etc.)
apoc.periodic10Periodic operations (iterate, commit, etc.)
apoc.search29Search operations (fulltext, fuzzy, regex, etc.)
apoc.scoring22Similarity scoring (cosine, jaccard, bm25, etc.)
apoc.spatial19Spatial operations (distance, bearing, geohash, etc.)
apoc.stats23Statistics (mean, median, correlation, etc.)
apoc.temporal26Temporal operations (format, parse, duration, etc.)
apoc.trigger24Trigger management (add, remove, enable, etc.)
apoc.warmup15Cache warmup (run, nodes, relationships, etc.)
apoc.xml23XML operations (parse, query, transform, etc.)
apoc.label27Label operations (add, remove, exists, etc.)
apoc.lock19Locking (nodes, relationships, etc.)
apoc.merge17Merge operations (node, relationship, etc.)
apoc.hashing18Hashing (md5, sha256, murmur, etc.)
apoc.graph15Graph operations (fromData, validate, etc.)
apoc.diff9Diff operations (nodes, maps, etc.)
apoc.cypher16Cypher utilities (run, parallel, etc.)
apoc.bitwise15Bitwise operations (and, or, xor, etc.)
apoc.atomic9Atomic operations (add, update, etc.)
apoc.number38Number formatting (format, parse, toHex, etc.)

Creating Custom Plugins

Plugin Interface

Create a Go file that exports a Plugin variable implementing the interface:

// my_plugin.go
package main

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

// Plugin is the exported symbol NornicDB loads
var Plugin = MyPlugin{}

type MyPlugin struct{}

func (p MyPlugin) Name() string    { return "myplugin" }
func (p MyPlugin) Version() string { return "1.0.0" }

func (p MyPlugin) Functions() map[string]apoc.FunctionInfo {
    return map[string]apoc.FunctionInfo{
        "apoc.myplugin.hello": {
            Handler:     Hello,
            Category:    "myplugin",
            Description: "Returns a greeting",
            Examples:    []string{"apoc.myplugin.hello('World') => 'Hello, World!'"},
        },
        "apoc.myplugin.double": {
            Handler:     Double,
            Category:    "myplugin",
            Description: "Doubles a number",
            Examples:    []string{"apoc.myplugin.double(21) => 42"},
        },
    }
}

func Hello(name string) string {
    return "Hello, " + name + "!"
}

func Double(n float64) float64 {
    return n * 2
}

Building Your Plugin

# Build the plugin (must use same Go version as NornicDB)
go build -buildmode=plugin -o my-plugin.so my_plugin.go

# Copy to plugins directory
cp my-plugin.so /path/to/nornicdb/plugins/

Using Your Plugin

After restarting NornicDB, your functions are available:

RETURN apoc.myplugin.hello('World')   // "Hello, World!"
RETURN apoc.myplugin.double(21)       // 42

Startup Logs

On startup, NornicDB logs loaded plugins:

๐Ÿ”Œ Loading Plugins from /app/plugins...
  โœ“ apoc.so: 964 functions loaded (v1.0.0)
  โœ“ my-plugin.so: 2 functions loaded (v1.0.0)
๐Ÿ“ฆ Total: 966 plugin functions available

Building the APOC Plugin

From the NornicDB source:

# Build using Makefile
make plugins

# Or manually
cd apoc/plugin-src/apoc
go build -buildmode=plugin -o ../../../apoc/built-plugins/apoc.so apoc_plugin.go

Docker Image Plugin Locations

All official Docker images include the pre-built APOC plugin:

ImagePlugins LocationFunctions
nornicdb-arm64-metal/app/plugins/apoc.so964
nornicdb-amd64-cuda/app/plugins/apoc.so964
nornicdb-amd64-cpu/app/plugins/apoc.so964

Troubleshooting

Plugin Not Loading

  1. Check plugin file exists and is readable:

    ls -la /app/plugins/
    
  2. Verify Go version compatibility (plugins must be built with same Go version):

    go version
    
  3. Check logs for errors:

    docker logs nornicdb 2>&1 | grep -i plugin
    

Function Not Found

  1. Check if function exists:

    CALL apoc.help('coll.sum')
    
  2. Verify plugin loaded at startup (check logs)

Invalid ELF Header

This error means the plugin was built for a different architecture:

  • Rebuild the plugin for the target architecture (arm64 vs amd64)
  • Ensure you're using go build -buildmode=plugin with matching platform

Platform Support

PlatformPlugin SupportNotes
Linux (amd64)โœ… FullNative Go plugin support
Linux (arm64)โœ… FullNative Go plugin support
macOS (arm64)โœ… FullNative Go plugin support
macOS (amd64)โœ… FullNative Go plugin support
WindowsโŒ NoneGo plugins not supported

For Windows, build NornicDB with APOC functions compiled in (not as plugin).

Performance

  • Plugins load once at startup (~100ms for APOC)
  • Function calls have minimal overhead (direct function pointer)
  • No difference in performance between built-in and plugin functions

Security Considerations

  • Plugins run with the same permissions as NornicDB
  • Only load plugins from trusted sources
  • Plugin code has full system access
  • Use Docker volume mounts for isolation
  • Review plugin source code before deployment