Design edge computing systems. Covers edge deployment patterns, IoT data processing, edge-cloud synchronization, latency optimization, offline-first architectures, and edge ML inference.
Edge computing architecture is the practice of placing compute, storage, and networking resources closer to data sources and end users—typically at or near the network edge, such as in cellular towers, retail stores, factories, or client premises. It matters when latency, bandwidth, or real-time responsiveness are critical: for industrial IoT control loops, video analytics at a stadium, autonomous vehicle coordination, or live audio/video streaming. Unlike centralized cloud deployments, edge architectures distribute workloads across a hierarchy of edge nodes, each capable of independent operation while synchronizing state with a central cloud.
An edge computing architecture consists of three primary layers: edge nodes, edge gateways, and cloud orchestration. Edge nodes run application logic and data processing tasks locally. Edge gateways act as entry points, aggregating traffic and managing connectivity to the cloud. Cloud orchestration coordinates deployment, monitoring, and updates across the distributed edge fleet.
Each edge node must be self-contained and resilient. Configuration is typically declarative and versioned. A node runs a lightweight runtime that supports containerized workloads.
A typical edge node configuration is a YAML file mounted at /etc/edge-node.yaml:
version: 1
node-id: "factory-01"
hostname: "edge-node-01"
network:
interfaces:
- name: "eth0"
ip: "192.168.1.10"
gateway: "192.168.1.1"
dns:
- "8.8.8.8"
- "1.1.1.1"
uplink:
type: "cellular"
apn: "iot.vodafone.com"
sim: "sim-12345"
bandwidth: "10Mbps"
latency: "80ms"
services:
- name: "camera-processor"
image: "registry.example.com/video-processor:v1.4"
ports:
- "8080:8080"
env:
- name: "PROCESSING_MODE"
value: "realtime"
- name: "BUFFER_SIZE"
value: "256"
volumes:
- source: "/data/cameras"
target: "/app/data"
restart: "always"
resources:
cpu: "2000m"
memory: "2Gi"
The runtime—usually a container engine like containerd or Docker Engine—loads this configuration at boot and starts services. The node uses systemd for service lifecycle, with unit files generated from the manifest:
[Unit]
Description=Camera Processor Service
After=network.target
[Service]
ExecStart=/usr/bin/docker run --rm \
-p 8080:8080 \
-v /data/cameras:/app/data \
-e PROCESSING_MODE=realtime \
-e BUFFER_SIZE=256 \
registry.example.com/video-processor:v1.4
Restart=always
RestartSec=10s
Environment=PATH=/usr/local/bin:/usr/bin:/bin
[Install]
WantedBy=multi-user.target
Edge gateways act as protocol translators, data aggregators, and fallback coordinators. They handle incoming data from edge nodes, route it to the cloud, and manage failover when connectivity is lost.
A gateway typically runs a lightweight message broker (e.g., mosquitto, NATS, or Apache Kafka) and a reverse proxy (e.g., nginx, Traefik, or Envoy).
To route traffic, a gateway uses a declarative routing configuration. For example, nginx config for edge traffic:
# /etc/nginx/conf.d/edge-routes.conf
upstream cloud_api {
server cloud.example.com:443 max_fails=3 fail_timeout=30s;
}
map $http_x_edge_node $node_zone {
default "global";
"factory-01" "zone-a";
"retail-05" "zone-b";
}
server {
listen 80;
server_name edge.example.com;
location /api/v1/ {
proxy_pass http://cloud_api;
proxy_set_header X-Edge-Node $http_x_edge_node;
proxy_set_header X-Node-Zone $node_zone;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_cache edge_cache;
proxy_cache_valid 200 10m;
proxy_cache_use_stale error timeout updating http_500 http_502;
}
location /stream/ {
proxy_pass http://streaming.example.com;
proxy_set_header Host $host;
proxy_set_header X-Edge-Node $http_x_edge_node;
chunked_transfer_encoding on;
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
}
}
When a node fails to reach the cloud, the gateway uses a health-check script to detect outages and trigger failover:
#!/bin/sh
# /usr/local/bin/check-cloud-connectivity.sh
set -euo pipefail
PING_HOST="cloud.example.com"
PING_TIMEOUT=5
if ! ping -c 1 -W $PING_TIMEOUT $PING_HOST; then
logger -t edge-gateway "Cloud unreachable; switching to local mode"
# Update routing to use local services
sed -i 's|proxy_pass http://cloud_api|proxy_pass http://local-services|g' /etc/nginx/conf.d/edge-routes.conf
systemctl reload nginx
# Start local stream processing
systemctl start stream-processor-local
else
logger -t edge-gateway "Cloud connectivity restored"
# Revert to cloud routing
sed -i 's|proxy_pass http://local-services|proxy_pass http://cloud_api|g' /etc/nginx/conf.d/edge-routes.conf
systemctl reload nginx
systemctl stop stream-processor-local
fi
Deployment of edge workloads is managed from a central cloud. The orchestration system maintains a desired state and pushes configuration and updates to edge nodes.
A deployment manifest describes the desired state of a fleet:
# /deployments/factory-01.yaml
apiVersion: edge.k8s.io/v1
kind: EdgeDeployment
metadata:
name: factory-01
labels:
region: "europe-west"
role: "production"
spec:
target:
node-id: "factory-01"
image: "factory-app:v2.1"
rolloutStrategy:
type: "rolling"
maxSurge: 2
maxUnavailable: 1
updatePolicy:
interval: "15m"
conditions:
- metric: "cpu.usage"
threshold: 75
window: "5m"
action: "scale-up"
- metric: "disk.io"
threshold: 80
window: "10m"
action: "trigger-backup"
services:
- name: "sensor-processor"
image: "registry.example.com/sensor-processor:v1.2"
replicas: 3
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"
ports:
- containerPort: 8080
name: "http"
readinessProbe:
httpGet:
path: "/health"
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
exec:
command:
- "/bin/sh"
- "-c"
- "curl -f http://localhost:8080/health || exit 1"
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 2
The orchestration system applies this manifest via kubectl, using a gitops model:
$ kubectl apply -f deployments/factory-01.yaml
edge.deployment.edge.k8s.io/factory-01 created
$ kubectl get edgedeployment factory-01 -o wide
NAME NODE-ID IMAGE STATUS UPDATES
factory-01 factory-01 factory-app:v2.1 Ready 3/3
When a deployment is updated, the orchestration system pushes changes to edge nodes via a binary update protocol. The edge node receives a delta update:
// /var/lib/edge-updates/2024-06-15-08:30:00.json
{
"version": "2.1",
"timestamp": "2024-06-15T08:30:00Z",
"changes": [
{
"type": "image",
"service": "sensor-processor",
"from": "registry.example.com/sensor-processor:v1.1",
"to": "registry.example.com/sensor-processor:v1.2"
},
{
"type": "config",
"path": "/etc/edge-node.yaml",
"patch": {
"services": [
{
"name": "camera-processor",
"env": [
{ "name": "BUFFER_SIZE", "value": "512" }
]
}
]
}
}
],
"checksum": "sha256:7c3a1d0b2f4c8e1f7d8a9b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2"
}
The edge node applies the update using systemd and containerd:
# Apply update script
#!/bin/sh
set -euo pipefail
UPDATE_DIR="/var/lib/edge-updates/2024-06-15-08:30:00"
UPDATE_JSON="$UPDATE_DIR/update.json"
# Apply config changes
jq -r '.changes[] | select(.type == "config") | .path' $UPDATE_JSON | while read config_path; do
patch -p0 -i <(jq -c '.changes[] | select(.type == "config") | .patch' $UPDATE_JSON) $config_path
done
# Update services
jq -r '.changes[] | select(.type == "image") | .service' $UPDATE_JSON | while read service; do
image=$(jq -r --arg s "$service" '.changes[] | select(.type == "image" and .service == $s) | .to' $UPDATE_JSON)
containerd --namespace k8s.io image pull $image
systemctl restart $service
done
# Verify
systemctl is-active --quiet sensor-processor || exit 1
systemctl is-active --quiet camera-processor || exit 1
logger -t edge-updater "Deployment applied successfully"
Edge computing is inherently prone to transient failures. The most common failure is connectivity loss. When a node loses connectivity, it must operate in local mode—processing data, storing events, and maintaining state—while awaiting reconnection.
A typical failure occurs when a node fails to apply an update during a network outage. The update process assumes that the new image is available on a remote registry, but the node cannot reach it.
# Error log from edge node during update
Jan 10 14:23:11 edge-node-01 containerd[1234]: Error pulling image registry.example.com/sensor-processor:v1.2: failed to resolve name: no such host
Jan 10 14:23:11 edge-node-01 edge-updater[5678]: Failed to apply update: image pull failed
Jan 10 14:23:11 edge-node-01 edge-updater[5678]: Fallback: using local image sensor-processor:v1.1
Jan 10 14:23:11 edge-node-01 edge-updater[5678]: Running update with fallback image
The system must detect this and trigger a local-first deployment strategy: the node runs on a cached version of the app, writes logs to local storage, and queues events for upload upon reconnection.
Another subtle failure is clock drift. Edge nodes often lack NTP synchronization. When logs are collected across multiple nodes, timestamps are inconsistent.
# Example log from two nodes with different clocks
2024-06-15T08:30:01Z [camera-processor] Processing frame 1245
2024-06-15T08:30:05Z [sensor-processor] Detected high temperature
2024-06-15T08:31:10Z [camera-processor] Frame 1246 processed
2024-06-15T08:32:45Z [sensor-processor] Temperature spike detected
The cloud system must align logs using a log correlation key—a unique ID generated at the edge node:
{
"trace_id": "a1b2c3d4e5f6",
"span_id": "x7y8z9w0",
"timestamp": "2024-06-15T08:30:01Z",
"event": "frame_processed",
"frame_id": 1245,
"node_id": "factory-01"
}
When the edge node reconnects, it uploads all buffered events in batches:
POST /api/v1/events/batch
Content-Type: application/json
Authorization: Bearer <token>
[
{
"trace_id": "a1b2c3d4e5f6",
"timestamp": "2024-06-15T08:30:01Z",
"event": "frame_processed",
"frame_id": 1245,
"node_id": "factory-01"
},
{
"trace_id": "a1b2c3d4e5f6",
"timestamp": "2024-06-15T08:31:10Z",
"event": "frame_processed",
"frame_id": 1246,
"node_id": "factory-01"
}
]
The cloud system deduplicates and validates the batch using ETag and timestamp metadata, ensuring that no event is lost or duplicated.
Configuration drift is a silent killer. Edge nodes often diverge from their intended state. The orchestration system must detect and reconcile drift.
A simple drift detection script runs periodically:
#!/bin/sh
# /usr/local/bin/check-drift.sh
set -euo pipefail
EXPECTED_CONFIG="/etc/edge-node.yaml.expected"
CURRENT_CONFIG="/etc/edge-node.yaml"
DIFF=$(diff $EXPECTED_CONFIG $CURRENT_CONFIG)
if [ -n "$DIFF" ]; then
logger -t edge-drift "Configuration drift detected"
echo "$DIFF" | mail -s "Edge Node Drift: $(hostname)" [email protected]
# Apply drift correction
cp $EXPECTED_CONFIG $CURRENT_CONFIG
systemctl reload docker
systemctl reload nginx
fi
The system uses git to version configurations:
$ git log --oneline --graph
* 3a1b2c3 Update camera processor config (2024-06-15)
* 7d8e9f0 Initial deployment (2024-06-10)
* a1b2c3d Add sensor-processor service (2024-06-05)
Each deployment is a Git commit with a changelog entry and a manifest file, enabling full traceability and rollbacks.
Synchronization between edge and cloud is not automatic. The system must handle eventual consistency, conflict resolution, and batched updates.
When an edge node is offline for hours, it accumulates thousands of events. Upon reconnection, it sends them in batches with a last-seen timestamp:
POST /api/v1/events
Content-Type: application/json
{
"last_seen": "2024-06-15T08:30:00Z",
"events": [
{
"timestamp": "2024-06-15T08:30:01Z",
"type": "frame_processed",
"frame_id": 1245
},
{
"timestamp": "2024-06-15T08:31:10Z",
"type": "frame_processed",
"frame_id": 1246
}
]
}
The cloud system uses a version vector to resolve conflicts:
{
"node_id": "factory-01",
"last_seen": "2024-06-15T08:31:10Z",
"version": {
"events": 1246,
"config": 3,
"services": 1
},
"checksum": "sha256:abc123def456"
}
On update, the cloud returns a patch to sync state:
HTTP/1.1 200 OK
Content-Type: application/json
{
"patches": [
{
"type": "config",
"applied": true,
"changes": [
"Updated BUFFER_SIZE to 512",
"Added new sensor type"
]
},
{
"type": "service",
"name": "camera-processor",
"updated": true,
"image": "registry.example.com/video-processor:v1.5"
}
],
"next_sync": "2024-06-15T08:45:00Z"
}
The edge node applies patches and schedules the next sync, ensuring continuous state alignment across the distributed system.
This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy