DEV Community

Victor Okefie
Victor Okefie

Posted on

Why I Built NexOps Local-First, and What Sub-50ms Operations Intelligence Actually Requires

The standard architecture for an operations dashboard is a cloud database, a server-side API, and a frontend that renders whatever the server returns. This architecture is logical, well-understood, and has one failure mode that nobody mentions in the product demo.
It fails when you need it most.

A field operation during a connectivity disruption. A warehouse under peak load with a saturated network. A construction site making a time-sensitive resource decision while the cloud sync is still pending.

The cloud-dependent dashboard is fast when conditions are good. When conditions are good, the decision is rarely urgent. When the decision is urgent, the conditions are usually not good.

NexOps is built local-first. This article explains the architectural decisions behind that choice and what sub-50ms operations intelligence actually requires to achieve.

The local-first architecture decision

Local-first means the intelligence lives where the decision is made — on the device, in the room, processed without a network round-trip in the critical path.
NexOps uses PGlite, a fully capable PostgreSQL instance that runs directly in the browser using WebAssembly. No server is required for query execution. The data is available regardless of network state.

import { PGlite } from '@electric-sql/pglite';
import { live } from '@electric-sql/pglite/live';

const db = new PGlite({
  extensions: { live }
});

await db.exec(`
  CREATE TABLE IF NOT EXISTS operations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    vendor_id TEXT NOT NULL,
    metric_name TEXT NOT NULL,
    metric_value NUMERIC NOT NULL,
    baseline_value NUMERIC NOT NULL,
    deviation_percent NUMERIC GENERATED ALWAYS AS (
      ((metric_value - baseline_value) / baseline_value) * 100
    ) STORED,
    recorded_at TIMESTAMPTZ DEFAULT NOW()
  );
`);
Enter fullscreen mode Exit fullscreen mode

The schema lives in the browser. The queries execute locally. The response time is a function of the device's processing speed — not the network, not the server, not the geographic distance to a data center.

Anomaly detection — consequence score over recency

The standard approach to anomaly detection in operations software is threshold-based alerting. A metric crosses a defined threshold and an alert fires. This approach has a well-known failure mode: alert fatigue. When everything triggers an alert, nothing is an alert.

NexOps uses a consequence score — a composite ranking that surfaces anomalies by what they cost if unaddressed, not by when they arrived or how far they have moved from baseline.

interface AnomalyScore {
  operationId: string;
  timeSensitivity: number;    // 0-1: how quickly does this deteriorate?
  downstreamImpact: number;   // 0-1: how many operations depend on this?
  baselineDeviation: number;  // 0-1: how far from normal?
  trajectoryScore: number;    // 0-1: is it getting worse?
  consequenceScore: number;   // composite: the ranking field
}

function calculateConsequenceScore(anomaly: AnomalyScore): number {
  return (
    anomaly.timeSensitivity * 0.35 +
    anomaly.downstreamImpact * 0.30 +
    anomaly.baselineDeviation * 0.20 +
    anomaly.trajectoryScore * 0.15
  );
}

Enter fullscreen mode Exit fullscreen mode

The weighting is deliberate. Time sensitivity carries the most weight because the value of early warning degrades fastest with time. Downstream impact carries the second-most weight because the most expensive failures are the ones that cascade. Baseline deviation and trajectory score are supporting signals — necessary but not sufficient on their own.

The result is a priority action queue that surfaces the most dangerous problem first — not the most recent, not the most visually prominent, the most consequential.

Real-time anomaly detection with live queries

PGlite's live query extension allows the operations view to update automatically when the underlying data changes — without polling, without websockets, without a server pushing updates.

import { live } from '@electric-sql/pglite/live';

const { initialResults, subscribe } = await db.live.query(`
  SELECT
    o.id,
    o.vendor_id,
    o.metric_name,
    o.deviation_percent,
    CASE
      WHEN ABS(o.deviation_percent) > 20 THEN 'critical'
      WHEN ABS(o.deviation_percent) > 10 THEN 'warning'
      ELSE 'normal'
    END as status
  FROM operations o
  WHERE recorded_at > NOW() - INTERVAL '24 hours'
  ORDER BY ABS(o.deviation_percent) DESC
`);

subscribe((results) => {
  updateOperationsView(results.rows);
});
Enter fullscreen mode Exit fullscreen mode

_The subscribe callback fires whenever the query result changes. The operations manager sees the current state of the system without refreshing, without manually pulling data, without a server in the loop.
_

The audit trail architecture

Every operation in NexOps is immutable. Nothing is edited. Nothing is deleted. The record of what happened, when, and in what sequence is permanent.

async function recordOperationEvent(
  db: PGlite,
  event: OperationEvent
): Promise<void> {
  await db.query(`
    INSERT INTO operation_audit_log (
      operation_id,
      event_type,
      previous_state,
      new_state,
      recorded_by,
      recorded_at
    ) VALUES ($1, $2, $3, $4, $5, NOW())
  `, [
    event.operationId,
    event.type,
    JSON.stringify(event.previousState),
    JSON.stringify(event.newState),
    event.userId
  ]);
}
Enter fullscreen mode Exit fullscreen mode

This is not logging for debugging purposes. It is an operational audit trail — the record that answers the Monday morning question of exactly what happened, in what sequence, and who knew what when.

In operations environments where liability matters — logistics contracts, construction timelines, regulatory compliance — the audit trail is not a nice-to-have. It is the evidence layer.

Local-first is not a technical preference. It is an architectural commitment to the principle that a decision tool cannot have a dependency that fails when the decision is most urgent.

Sub-50ms intelligence is not a performance target. It is what happens when you remove the server from the critical path.

The operations environment in Nigeria — and in most of the markets that international SaaS products were not built for — requires tools built on these commitments, not tools that assume the conditions those commitments were designed to handle.

NexOps is running live at nexops-three.vercel.app

Top comments (0)