Architecture

How all the pieces fit together — from machine data to KPI APIs.

System Overview

Internet
    │
    ▼
┌──────────────────────────────────────────────────────┐
│  Caddy (TLS termination, reverse proxy)              │
└──────────────────────┬───────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────┐
│  fnkit-gateway (authentication, routing, rate limit)  │
└──────────────────────┬───────────────────────────────┘
                       │
          ┌────────────┼────────────────────┐
          │            │                    │
          ▼            ▼                    ▼
    HTTP Functions   MQTT Functions    Shared Services
    (uns-cache,      (uns-sim,         (fnkit-cache,
     uns-log,         uns-framework)    fnkit-postgres,
     uns-state,                         MQTT broker)
     uns-stoppage,
     uns-productivity,
     uns-input,
     uns-kpi)

All containers run on a shared Docker network (fnkit-network). External access goes through Caddy → gateway. Internal communication happens directly between containers.

Data Flow

The system processes data in three stages: capture, process, and report.

Stage 1: Capture

ComponentRole
uns-simPublishes machine data (status, program, tool) to MQTT every 3 seconds
MQTT BrokerDistributes messages to all subscribers
uns-frameworkSubscribes to v1.0/# and caches every message to Valkey

For each message: current value → uns:data:<topic>, previous value → uns:prev:<topic>

Stage 2: Process

Processing functions read from Valkey and write to PostgreSQL:

FunctionReadsWrites
uns-state/status topics from ValkeyState durations → uns_state table
uns-stoppageuns_state tableClassified stoppages → uns_stoppage table
uns-productivity/program topics from ValkeyProduction runs → uns_productivity table
uns-inputHTTP POST bodyManual entries → uns_input table
uns-logAny topics from ValkeyChange snapshots → uns_log table
uns-cacheAny topics from ValkeyJSON response (no DB write)

Stage 3: Report

uns-kpi is a pure read function. It queries all 4 PostgreSQL tables and computes manufacturing KPIs on demand — utilisation, availability, throughput, MTBF/MTTR, stoppage pareto, and scrap.

Infrastructure Components

fnkit-network

A Docker bridge network that all containers join. Functions communicate by container name:

fnkit-cache:6379      → Valkey (Redis-compatible cache)
fnkit-postgres:5432   → PostgreSQL database
mqtt-broker:1883      → MQTT broker (internal)
mqtt-broker:8883      → MQTT broker (TLS)

fnkit-cache (Valkey)

Valkey — an open-source Redis-compatible cache. Used for:

PurposeKey Pattern
UNS topic data — current and previous valuesuns:data:*, uns:prev:*
Topic registry — set of all discovered topicsuns:topics
Function config — runtime configurationfnkit:config:*
Metadata — message counts, timestampsuns:meta:*

fnkit-postgres (PostgreSQL)

Stores all persistent data. All tables are auto-created on first run:

TableWritten byPurpose
uns_loguns-logChange snapshots with full hierarchy
uns_stateuns-stateMachine state durations
uns_stoppageuns-stoppageClassified stoppage reasons
uns_productivityuns-productivityProduction run metrics
uns_inputuns-inputManual operator entries

fnkit-gateway

The API gateway handles authentication (Bearer token), routing (URL paths → function containers), and rate limiting.

GET  /uns-cache         → uns-cache container
POST /uns-log           → uns-log container
GET  /uns-kpi?hours=8   → uns-kpi container
POST /uns-input         → uns-input container

Caddy

Provides automatic TLS (Let's Encrypt), reverse proxy, and HTTP/2 support.

Function Types

TypeScaffold CommandTriggerUsed by
Go HTTPfnkit goHTTP requestuns-log, uns-state, uns-productivity, uns-kpi
Node.js HTTPfnkit nodeHTTP requestuns-cache, uns-stoppage, uns-input
Go MQTTfnkit go-mqttMQTT messageuns-framework
Node.js MQTTfnkit node-mqttMQTT messageuns-sim

Configuration Pattern

All runtime configuration is stored in Valkey, not in environment files:

fnkit:config:uns-log          → {"table":"uns_log","topics":[...]}
fnkit:config:uns-state        → {"table":"uns_state","topics":[...]}
fnkit:config:uns-productivity → {"table":"uns_productivity","topics":[...]}

Each function reads its config using FUNCTION_TARGET as the key. Config is cached in-memory for 30 seconds. You can change what topics a function monitors without redeploying the container.

Deployment Model

# Local development
docker compose up -d
curl http://localhost:8080/

# Remote deployment (GitOps)
fnkit deploy remote --host root@server
git push deploy main

Each function is independently deployable. Updating uns-kpi doesn't affect uns-state. Rolling back uns-stoppage doesn't touch uns-productivity.