tutorial

Monitoring Speckle 3D Data Platform with Vigilmon

Speckle is the open source version control platform for AEC 3D models and BIM data — but self-hosted Speckle needs active monitoring. Here's how to monitor Speckle server health, PostgreSQL, object storage, Redis, and the preview service with Vigilmon.

Speckle is the open source platform for version control, collaboration, and data exchange across AEC (architecture, engineering, and construction) tools — Revit, Rhino, Grasshopper, AutoCAD, and more. When architecture firms and engineering consultants self-host Speckle, they own the reliability of the platform that stores their project 3D geometry, BIM data, and model history. A Speckle server outage means Revit connectors can't push model updates, Grasshopper scripts can't pull geometry, and project teams lose real-time collaboration. Vigilmon gives you the external monitoring layer to catch Speckle failures before they block your AEC workflows.

What You'll Set Up

  • Speckle server health endpoint monitoring
  • PostgreSQL database connectivity checks
  • Object storage (MinIO/S3) availability and capacity monitoring
  • Redis health and connectivity checks
  • GraphQL API latency monitoring
  • WebSocket server health monitoring
  • Preview service health tracking
  • Model upload throughput heartbeats

Prerequisites

  • A self-hosted Speckle Server deployment (Docker Compose or Kubernetes)
  • Access to the server running Speckle's containers
  • A free Vigilmon account

Why Monitoring Matters for Speckle

Speckle has a microservice-like architecture with four independently-failable components: the Node.js server process, PostgreSQL, object storage (MinIO or S3), and Redis. Any one of them failing degrades Speckle differently:

  • Server process failure — all API calls fail; connectors in Revit/Rhino show connection errors
  • PostgreSQL failure — project metadata, branches, commits, and user accounts become inaccessible
  • Object storage failure — 3D geometry and BIM data can't be read or written; model viewing fails
  • Redis failure — WebSocket real-time events stop; background job queuing stops; live collaboration breaks

The preview service (thumbnail rendering) is less critical — a failure means version thumbnails show as broken images, but core collaboration still works.

Monitoring Speckle means watching all four infrastructure components independently, plus the application-level API surfaces (REST, GraphQL, WebSocket) that your AEC connectors use.


Key Metrics to Monitor

| Metric | Why It Matters | Alert Threshold | |--------|---------------|-----------------| | Speckle server health endpoint | Server process availability | Any failure | | PostgreSQL connectivity | Project/version metadata | Any failure | | Object storage connectivity | 3D geometry availability | Any failure | | Object storage capacity | Model data growth | > 80% | | Redis connectivity | Real-time collaboration | Any failure | | GraphQL API p95 latency | Model query performance | > 2 seconds | | WebSocket connection health | Live collaboration | Server failure | | Preview service health | Thumbnail generation | Queue backup | | Model upload throughput | Connector data ingestion | Drop to zero | | Auth login success rate | User access | Auth failures |


Step 1: Monitor Speckle Server Health

Speckle Server exposes a health endpoint that reports overall server status. Add a Vigilmon HTTP monitor:

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. URL: https://your-speckle-server.com/api/health (or http://localhost:3000/api/health if local).
  4. Check interval: 1 minute.
  5. Expected status: 200.
  6. Click Save.

If your Speckle deployment doesn't expose /api/health, use the root API endpoint:

https://your-speckle-server.com/api

A 200 response from the Speckle API root confirms the Node.js server process is running and accepting connections.

Alert condition: immediate notification on any non-200 response — Speckle server failure blocks all AEC connector operations.


Step 2: Monitor PostgreSQL Health

PostgreSQL stores all Speckle metadata: projects (streams), branches (model versions), commits, objects (hashed model data references), user accounts, and server configuration. Database failure makes all of this inaccessible.

Create a heartbeat probe script on your Speckle server:

#!/bin/bash
# /usr/local/bin/speckle-db-check.sh
POSTGRES_HOST="localhost"
POSTGRES_PORT="5432"
POSTGRES_DB="speckle"
POSTGRES_USER="speckle"
POSTGRES_PASSWORD="yourpassword"
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_DB_HEARTBEAT_ID"

# Run a lightweight query to verify connectivity and response time
START=$(date +%s%N)
RESULT=$(PGPASSWORD="$POSTGRES_PASSWORD" psql \
  -h "$POSTGRES_HOST" \
  -p "$POSTGRES_PORT" \
  -U "$POSTGRES_USER" \
  -d "$POSTGRES_DB" \
  -t -c "SELECT COUNT(*) FROM users LIMIT 1;" 2>/dev/null)
EXIT_CODE=$?
END=$(date +%s%N)
LATENCY_MS=$(( (END - START) / 1000000 ))

if [ $EXIT_CODE -eq 0 ] && [ $LATENCY_MS -lt 2000 ]; then
    curl -s "$HEARTBEAT_URL" > /dev/null
    echo "PostgreSQL OK: ${LATENCY_MS}ms"
else
    echo "ALERT: PostgreSQL check failed (exit: $EXIT_CODE, latency: ${LATENCY_MS}ms)"
fi

For Docker Compose deployments, run this inside the Speckle network:

#!/bin/bash
# Run inside Docker on the speckle server host
docker exec speckle-postgres psql -U speckle -d speckle \
  -c "SELECT COUNT(*) FROM users;" > /dev/null 2>&1
if [ $? -eq 0 ]; then
    curl -s "https://vigilmon.online/api/heartbeat/YOUR_DB_HEARTBEAT_ID" > /dev/null
fi

Add to cron every 5 minutes. Configure the Vigilmon heartbeat with a 10-minute grace period.


Step 3: Monitor Object Storage Health

Speckle stores all 3D model geometry and BIM data as content-addressed objects in S3-compatible object storage (MinIO for self-hosted). This is where the actual geometry lives — the PostgreSQL database only stores metadata and hashes. Object storage failure means model viewing and connector sync both fail.

For MinIO (self-hosted):

#!/bin/bash
# /usr/local/bin/speckle-minio-check.sh
MINIO_ENDPOINT="http://localhost:9000"
MINIO_ACCESS_KEY="minioadmin"
MINIO_SECRET_KEY="minioadmin"
BUCKET_NAME="speckle-objects"
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_MINIO_HEARTBEAT_ID"

# Check MinIO health
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" "$MINIO_ENDPOINT/minio/health/live")

if [ "$HEALTH" = "200" ]; then
    # Also check storage capacity
    DISK_USAGE=$(df /data/minio 2>/dev/null | awk 'NR==2 {print $5}' | tr -d '%')
    if [ -z "$DISK_USAGE" ] || [ "$DISK_USAGE" -lt 80 ]; then
        curl -s "$HEARTBEAT_URL" > /dev/null
        echo "MinIO OK, disk: ${DISK_USAGE}%"
    else
        echo "ALERT: MinIO disk usage critical: ${DISK_USAGE}%"
    fi
else
    echo "ALERT: MinIO health check failed (HTTP $HEALTH)"
fi

Add a Vigilmon HTTP monitor directly for MinIO's health endpoint:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: http://your-speckle-host:9000/minio/health/live
  3. Expected status: 200
  4. Check interval: 2 minutes

For the storage capacity heartbeat, add the shell script to cron every 15 minutes.

For AWS S3:

#!/bin/bash
# /usr/local/bin/speckle-s3-check.sh
BUCKET_NAME="your-speckle-bucket"
AWS_REGION="us-east-1"
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_S3_HEARTBEAT_ID"

# List bucket (confirms connectivity and permissions)
aws s3api head-bucket --bucket "$BUCKET_NAME" --region "$AWS_REGION" > /dev/null 2>&1
if [ $? -eq 0 ]; then
    curl -s "$HEARTBEAT_URL" > /dev/null
    echo "S3 bucket accessible"
else
    echo "ALERT: S3 bucket $BUCKET_NAME inaccessible"
fi

Step 4: Monitor Redis Health

Redis powers Speckle's WebSocket session management, real-time subscription events, and background job queuing. Redis failure degrades Speckle in two ways: WebSocket-based real-time collaboration stops working, and background jobs (like preview generation) queue but don't process.

#!/bin/bash
# /usr/local/bin/speckle-redis-check.sh
REDIS_HOST="localhost"
REDIS_PORT="6379"
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_REDIS_HEARTBEAT_ID"

# Ping Redis
PONG=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" PING 2>/dev/null)

if [ "$PONG" = "PONG" ]; then
    # Also check memory usage
    MEMORY_INFO=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" INFO memory 2>/dev/null)
    USED_MB=$(echo "$MEMORY_INFO" | grep 'used_memory:' | awk -F: '{print $2/1024/1024}' | cut -d. -f1)
    curl -s "$HEARTBEAT_URL" > /dev/null
    echo "Redis OK, memory: ${USED_MB}MB"
else
    echo "ALERT: Redis not responding"
fi

For Docker Compose:

docker exec speckle-redis redis-cli PING | grep -q PONG && \
    curl -s "https://vigilmon.online/api/heartbeat/YOUR_REDIS_HEARTBEAT_ID" > /dev/null

Run every 2 minutes. Alert condition: any Redis connectivity failure causes real-time collaboration failure.


Step 5: Monitor GraphQL API Latency

Speckle's GraphQL API powers the web frontend and can be queried by custom AEC tooling. High latency in the GraphQL API indicates PostgreSQL pressure, high model complexity, or server resource exhaustion.

Add a Vigilmon HTTP monitor with a response time alert:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: https://your-speckle-server.com/graphql
  3. Method: POST
  4. Body: {"query": "{ serverInfo { name version } }"}
  5. Header: Content-Type: application/json
  6. Expected status: 200
  7. Check interval: 2 minutes

For the p95 latency alert, use Vigilmon's response time threshold setting:

  • Alert if response time exceeds 2000ms (2 seconds)

This catches the slow-query scenarios that don't cause outright failures but degrade the experience for model loading and project browsing.


Step 6: Monitor WebSocket Server Health

Speckle's real-time collaboration features (live model updates, presence, notifications) run over WebSocket. WebSocket failures don't affect REST API calls but silently break all real-time collaboration.

Test WebSocket connectivity from a probe script:

#!/bin/bash
# /usr/local/bin/speckle-ws-check.sh
SPECKLE_HOST="your-speckle-server.com"
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_WS_HEARTBEAT_ID"

# Use wscat or websocat to test WebSocket handshake
# Install: npm install -g wscat
WS_RESULT=$(timeout 5 wscat -c "wss://$SPECKLE_HOST" --no-check 2>&1 | head -3)

if echo "$WS_RESULT" | grep -q "Connected"; then
    curl -s "$HEARTBEAT_URL" > /dev/null
    echo "WebSocket OK"
elif echo "$WS_RESULT" | grep -q "101\|Upgrade\|switching"; then
    curl -s "$HEARTBEAT_URL" > /dev/null
    echo "WebSocket handshake OK"
else
    echo "ALERT: WebSocket connection failed: $WS_RESULT"
fi

Alternatively, monitor the Socket.io upgrade endpoint directly:

# Check that Socket.io is responding to upgrade requests
HTTP_RESULT=$(curl -s -o /dev/null -w "%{http_code}" \
  "https://your-speckle-server.com/socket.io/?transport=polling")
if [ "$HTTP_RESULT" = "200" ]; then
    curl -s "$HEARTBEAT_URL" > /dev/null
fi

Step 7: Monitor Preview Service Health

Speckle's preview service renders 2D thumbnail images of 3D model versions. It runs as a separate worker container. While preview service failure doesn't block collaboration, it causes version thumbnails to appear as broken images in the web frontend.

#!/bin/bash
# /usr/local/bin/speckle-preview-check.sh
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_PREVIEW_HEARTBEAT_ID"

# Check if preview service container is running
PREVIEW_STATUS=$(docker inspect --format='{{.State.Status}}' speckle-preview-service 2>/dev/null)

if [ "$PREVIEW_STATUS" = "running" ]; then
    # Check preview queue depth via Redis
    QUEUE_DEPTH=$(redis-cli -h localhost LLEN "bull:preview:wait" 2>/dev/null || echo "0")
    if [ "$QUEUE_DEPTH" -lt 1000 ]; then
        curl -s "$HEARTBEAT_URL" > /dev/null
        echo "Preview service OK, queue: $QUEUE_DEPTH"
    else
        echo "ALERT: Preview queue backed up: $QUEUE_DEPTH items"
    fi
else
    echo "ALERT: Preview service container not running (status: $PREVIEW_STATUS)"
fi

Configure this heartbeat with a 10-minute grace period — preview is non-critical and brief interruptions are acceptable.


Step 8: Monitor Model Upload Throughput

For active AEC teams, model upload throughput is a leading indicator of connector health. A drop to zero uploads often indicates a connector version incompatibility, network issue, or server-side rejection of incoming model data.

#!/bin/bash
# /usr/local/bin/speckle-upload-check.sh
POSTGRES_USER="speckle"
POSTGRES_DB="speckle"
POSTGRES_PASSWORD="yourpassword"
HEARTBEAT_URL="https://vigilmon.online/api/heartbeat/YOUR_UPLOAD_HEARTBEAT_ID"
STATE_FILE="/tmp/speckle-last-object-count"

# Count total objects created in the last hour
CURRENT_COUNT=$(PGPASSWORD="$POSTGRES_PASSWORD" psql \
  -U "$POSTGRES_USER" -d "$POSTGRES_DB" -t \
  -c "SELECT COUNT(*) FROM objects WHERE \"createdAt\" > NOW() - INTERVAL '1 hour';" \
  2>/dev/null | tr -d ' ')

LAST_COUNT=$(cat "$STATE_FILE" 2>/dev/null || echo "-1")
echo "$CURRENT_COUNT" > "$STATE_FILE"

# On first run, just establish baseline
if [ "$LAST_COUNT" = "-1" ]; then
    curl -s "$HEARTBEAT_URL" > /dev/null
    echo "Baseline established: $CURRENT_COUNT objects in last hour"
    exit 0
fi

# Alert if upload throughput drops significantly (> 90% reduction)
if [ "$CURRENT_COUNT" -gt 0 ] || [ "$LAST_COUNT" -lt 10 ]; then
    curl -s "$HEARTBEAT_URL" > /dev/null
    echo "Upload throughput OK: $CURRENT_COUNT objects in last hour"
else
    echo "ALERT: Upload throughput dropped to zero (was $LAST_COUNT)"
    # Heartbeat withheld
fi

Note: Calibrate this to your team's actual usage pattern. Some teams batch uploads during working hours only.


Step 9: Configure Alerting

Set up notification channels in Vigilmon for your Speckle monitors:

  1. Go to Settings → Notifications.
  2. Add Slack, email, Microsoft Teams, or PagerDuty.
  3. Route by component criticality.

Recommended routing for Speckle:

| Monitor | Severity | Notification | |---------|----------|-------------| | Speckle server down | Critical | Immediate: Slack + email | | PostgreSQL failure | Critical | Immediate: Slack + email | | Object storage failure | Critical | Immediate: Slack + email | | Redis failure | High | Immediate: Slack | | GraphQL latency > 2s | High | Slack | | WebSocket failure | High | Slack | | Object storage > 80% | Medium | Email | | Preview service down | Low | Email (next business day) | | Upload throughput → zero | Medium | Slack |


Step 10: Test Your Monitors

Verify each alert fires correctly:

# Test Speckle server alert
docker-compose stop speckle-server
# → Vigilmon HTTP monitor alerts within 1-2 minutes
docker-compose start speckle-server

# Test PostgreSQL alert
docker-compose stop speckle-postgres
# → DB heartbeat missed within 10 minutes
docker-compose start speckle-postgres

# Test Redis alert
docker-compose stop speckle-redis
# → Redis heartbeat missed within 5 minutes
docker-compose start speckle-redis

# Test object storage capacity alert
# Fill MinIO disk to > 80%
# → Disk check heartbeat withheld; Vigilmon alerts

# Test preview service alert
docker-compose stop speckle-preview
# → Preview heartbeat missed within 10 minutes
docker-compose start speckle-preview

Conclusion

Self-hosted Speckle is the collaborative backbone for AEC project teams — model uploads from Revit, geometry queries from Grasshopper, and real-time coordination between structural and MEP engineers all depend on it. With Vigilmon monitoring each layer of Speckle's stack — the Node.js server, PostgreSQL, MinIO/S3, Redis, and the GraphQL/WebSocket APIs — you'll catch failures before they disrupt a design coordination session or block a deadline-driven model submission.

Start with the server health check and PostgreSQL heartbeat. Then add object storage and Redis monitoring — those are the component failures most likely to cause silent partial degradation rather than a total outage.

Start monitoring your Speckle server with Vigilmon →

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →