Skip to content

Edge Architecture: Fintech Offline-First

Ruvon Edge is designed for fintech edge devices—POS terminals, ATMs, mobile card readers, and kiosks that must operate offline and sync when connectivity is available.

The Edge Computing Challenge

Traditional cloud-first architectures assume always-on connectivity:

POS Terminal → Network → Cloud Server → Response

Problems in fintech: - Network unreliable: Basement restaurants, subway stations, rural areas - Latency unacceptable: Payment must complete in < 2 seconds - Downtime costly: Lost sales if terminal can't process transactions - Compliance required: PCI-DSS mandates local processing for sensitive data

Edge-First Architecture

Ruvon Edge inverts the model: edge devices are autonomous, cloud provides coordination.

┌─────────────────────────────────────────┐
│          CLOUD CONTROL PLANE            │
│     (PostgreSQL + Ruvon Server)         │
│                                          │
│  ┌────────────────────────────────┐    │
│  │  Device Registry API           │    │
│  │  - Register devices            │    │
│  │  - Track device status         │    │
│  └────────────────────────────────┘    │
│                                          │
│  ┌────────────────────────────────┐    │
│  │  Config Server (ETag-based)    │    │
│  │  - Push workflow updates       │    │
│  │  - Push fraud rules            │    │
│  │  - Push pricing tables         │    │
│  └────────────────────────────────┘    │
│                                          │
│  ┌────────────────────────────────┐    │
│  │  Transaction Sync API          │    │
│  │  - Receive offline transactions│    │
│  │  - Settle batches              │    │
│  │  - Reconcile ledgers           │    │
│  └────────────────────────────────┘    │
└──────────────┬───────────────────────────┘
               │ HTTP/MQTT (intermittent)
┌──────────────▼───────────────────────────┐
│      EDGE DEVICE (POS/ATM/Kiosk)         │
│       (SQLite + RuvonEdgeAgent)          │
│                                           │
│  ┌────────────────────────────────┐     │
│  │  RuvonEdgeAgent                │     │
│  │  - Run workflows locally       │     │
│  │  - SQLite persistence          │     │
│  │  - Store-and-Forward queue     │     │
│  └────────────────────────────────┘     │
│                                           │
│  ┌────────────────────────────────┐     │
│  │  SyncManager                   │     │
│  │  - Push transactions to cloud  │     │
│  │  - Pull config updates         │     │
│  │  - Handle network failures     │     │
│  └────────────────────────────────┘     │
│                                           │
│  ┌────────────────────────────────┐     │
│  │  ConfigManager                 │     │
│  │  - ETag-based update detection │     │
│  │  - Hot-reload workflows        │     │
│  │  - Version management          │     │
│  └────────────────────────────────┘     │
└───────────────────────────────────────────┘

Key Concepts

1. Store-and-Forward (SAF)

Transactions processed offline, synced when online:

Customer swipes card (offline)
Edge device validates card locally
Workflow processes payment (SQLite)
Transaction queued for sync
Customer receives receipt (immediate!)
[Hours later, network available]
SyncManager uploads transaction batch
Cloud settlement gateway processes

Key Principle: Customer experience is immediate, settlement is eventual.

2. Floor Limits

Low-value transactions approved offline, high-value deferred to cloud:

workflow_type: "PaymentProcessing"
steps:
  - name: "Validate_Card"
    type: "STANDARD"
    function: "edge.validate_card_offline"

  - name: "Check_Amount"
    type: "DECISION"
    routes:
      - condition: "state.amount <= 50"
        target: "Approve_Offline"  # Fast path
      - condition: "state.amount > 50"
        target: "Queue_For_Cloud_Auth"  # Defer to cloud

Regulation: PCI-DSS allows offline approval up to floor limit (typically $25-$100).

3. Config Push (ETag-based)

Hot-deploy fraud rules without firmware updates:

Edge device polls: GET /api/v1/config/fraud-rules
    Headers: If-None-Match: "v1.2.0"

Cloud responds:
    304 Not Modified (config unchanged)

[Admin updates fraud rules to v1.3.0]

Edge device polls: GET /api/v1/config/fraud-rules
    Headers: If-None-Match: "v1.2.0"

Cloud responds:
    200 OK
    ETag: "v1.3.0"
    Body: {"rules": [...]}

Edge device:
    - Downloads new rules
    - Validates config
    - Hot-reloads workflows
    - Updates local ETag

Benefit: No device downtime, no firmware flash, instant deployment.

4. Encryption at Rest

Edge devices store sensitive data encrypted:

# src/ruvon_edge/encryption.py
from cryptography.fernet import Fernet

class EncryptedPersistence:
    def __init__(self, sqlite_path, encryption_key):
        self.sqlite = SQLitePersistenceProvider(sqlite_path)
        self.cipher = Fernet(encryption_key)

    async def save_workflow(self, workflow_id, workflow_dict):
        # Encrypt sensitive fields
        encrypted_state = self.cipher.encrypt(
            json.dumps(workflow_dict['state']).encode()
        )

        workflow_dict['state'] = encrypted_state.decode()
        await self.sqlite.save_workflow(workflow_id, workflow_dict)

Compliance: Meets PCI-DSS requirement for data-at-rest encryption.

Edge Device Capabilities

Offline Operations

What works offline: - ✅ Card validation (EMV chip, magnetic stripe) - ✅ PIN verification (local secure element) - ✅ Floor limit approval (< $50) - ✅ Receipt printing - ✅ Transaction logging - ✅ Fraud rule evaluation (locally cached rules)

What requires connectivity: - ❌ High-value authorization (> floor limit) - ❌ Real-time fraud scoring (cloud ML models) - ❌ Account balance checks - ❌ Multi-currency conversion (live exchange rates) - ❌ Settlement

Hardware Integration

# src/ruvon_edge/hardware/
├── card_reader.py       # EMV/MSR/contactless
├── pin_pad.py           # Secure PIN entry
├── printer.py           # Receipt printer
├── display.py           # Customer/merchant display
└── secure_element.py    # Crypto operations

Example: Card validation:

from ruvon_edge.hardware import CardReader

def validate_card_offline(state: PaymentState, context: StepContext) -> dict:
    reader = CardReader()

    # Read card
    card_data = reader.read_emv_chip()

    # Validate locally
    if not card_data.is_valid_checksum():
        return {"approved": False, "reason": "invalid_card"}

    # Check expiration
    if card_data.is_expired():
        return {"approved": False, "reason": "expired_card"}

    # Check against local blacklist
    if card_data.pan in state.blacklisted_cards:
        return {"approved": False, "reason": "blocked_card"}

    return {
        "approved": True,
        "card_type": card_data.card_type,
        "masked_pan": card_data.masked_pan
    }

Sync Strategies

1. Push on Connectivity

Device detects network, immediately syncs:

class SyncManager:
    async def on_network_available(self):
        # Network just came online
        await self.sync_pending_transactions()
        await self.sync_config_updates()

    async def sync_pending_transactions(self):
        # Get all unsynced transactions
        pending = await self.persistence.list_workflows(
            status="COMPLETED",
            synced=False
        )

        # Upload batch
        batch = [self.serialize_transaction(w) for w in pending]
        response = await self.cloud_api.post("/api/v1/transactions/batch", batch)

        # Mark as synced
        for workflow_id in response['synced_ids']:
            await self.persistence.mark_synced(workflow_id)

2. Scheduled Batch Sync

Device syncs every N minutes, regardless of connectivity:

async def scheduled_sync_daemon(sync_manager):
    while True:
        try:
            await sync_manager.sync_pending_transactions()
        except NetworkError:
            logger.warning("Sync failed, will retry")

        await asyncio.sleep(300)  # 5 minutes

3. Low-Priority Background Sync

Sync only when device idle:

class SyncManager:
    async def background_sync(self):
        # Check if device is idle (no active workflows)
        active_count = await self.persistence.count_workflows(status="ACTIVE")

        if active_count == 0:
            # Device idle, safe to sync
            await self.sync_pending_transactions()
        else:
            # Device busy, defer sync
            logger.debug("Deferring sync, device busy")

Use Cases

1. POS Terminal (Retail)

Scenario: Coffee shop in subway station with spotty WiFi.

Workflow:

workflow_type: "CoffeePurchase"
steps:
  - name: "Read_Card"
    type: "STANDARD"
    function: "edge.read_card"

  - name: "Check_Floor_Limit"
    type: "DECISION"
    routes:
      - condition: "state.amount <= 25"
        target: "Approve_Offline"
      - default: "Queue_For_Auth"

  - name: "Approve_Offline"
    type: "STANDARD"
    function: "edge.approve_offline"

  - name: "Print_Receipt"
    type: "STANDARD"
    function: "edge.print_receipt"

  - name: "Queue_For_Settlement"
    type: "STANDARD"
    function: "edge.queue_for_sync"

Result: Customer gets receipt in 2 seconds, settlement happens hours later.

2. ATM (Cash Withdrawal)

Scenario: ATM in rural area with slow satellite link.

Offline capability: - Card validation - PIN verification - Balance check (cached from last sync) - Dispense cash (up to daily limit) - Update local ledger - Queue withdrawal for settlement

Online requirement: - Balance updates synced every 5 minutes - High-value withdrawals (> $500) require real-time auth

3. Mobile Card Reader (Delivery)

Scenario: Food delivery driver with mobile reader, roaming between dead zones.

Workflow:

workflow_type: "DeliveryPayment"
steps:
  - name: "Validate_Card"
  - name: "Approve_Offline"  # Always offline (< $100)
  - name: "Update_Delivery_Status"
  - name: "Queue_For_Sync"

Sync strategy: Batch upload at end of shift.

Security Considerations

1. Device Authentication

Each device has unique credentials:

# Device registration
device_id = "POS-12345"
device_secret = generate_secret()  # Stored in secure element

# API authentication
headers = {
    "Authorization": f"Device {device_id}:{sign(device_secret, request_body)}"
}

2. Transaction Integrity

Transactions signed with device key:

transaction = {
    "amount": 50.00,
    "timestamp": "2026-02-13T10:15:00Z",
    "card_hash": "...",
}

signature = sign(device_secret, transaction)
transaction['signature'] = signature

# Cloud verifies signature
if not verify_signature(transaction, device_public_key):
    reject("Invalid signature")

3. Config Validation

Downloaded configs validated before loading:

def validate_config(config, expected_checksum):
    # Verify checksum
    if sha256(config) != expected_checksum:
        raise ConfigCorruptionError("Checksum mismatch")

    # Validate schema
    ConfigSchema.validate(config)

    # Check signature
    if not verify_signature(config, cloud_public_key):
        raise ConfigTamperingError("Invalid signature")

    return config

Package Footprint

Ruvon ships as three separate wheels. Edge devices install only ruvon-edge, which pulls in the ruvon-sdk core but never installs the 10 MB cloud control plane.

Scenario Install command Disk RAM
Minimal (offline payment, no AI) pip install ruvon-edge ~15–20 MB ~50 MB
With monitoring + WebSocket pip install 'ruvon-edge[edge]' ~30–35 MB ~65 MB
With ONNX fraud scoring pip install 'ruvon-edge[edge]' && pip install onnxruntime ~80–600 MB* ~115–165 MB
With TFLite pip install 'ruvon-edge[edge]' && pip install tflite-runtime ~50–250 MB* ~85–115 MB

* Varies by model size. Model files are downloaded separately.

For full footprint details, included/excluded files, and hardware requirements, see Edge Device Package Footprint.

Deployment

Edge Agent Installation

# Install Ruvon Edge SDK (edge device — no cloud code included)
pip install 'ruvon-edge[edge]'

# Optional: add ONNX inference for on-device ML
pip install onnxruntime>=1.16.0

# Run your edge agent
python edge_agent.py

Cloud Server Setup

# Deploy Ruvon Server with edge endpoints
docker-compose -f docker/docker-compose.edge.yml up -d

# Registers edge API routes:
# - POST /api/v1/devices/register
# - GET /api/v1/devices/{device_id}/config
# - POST /api/v1/transactions/batch
# - GET /api/v1/devices/{device_id}/commands

Monitoring

Edge Device Metrics

# Device health
await device_api.report_metrics({
    "disk_usage_percent": 45,
    "memory_usage_mb": 128,
    "pending_transactions": 15,
    "last_sync": "2026-02-13T10:00:00Z",
    "network_available": False
})

Cloud Dashboard

Device Status:
├── Online: 850 devices
├── Offline (< 1h): 120 devices
├── Offline (> 24h): 5 devices (ALERT!)
└── Total: 975 devices

Pending Transactions:
├── Last hour: 1,245 transactions
├── Last 24h: 18,567 transactions
├── Unsynced: 3,421 transactions (ALERT!)

Config Version Distribution:
├── v1.5.0: 920 devices (95%)
├── v1.4.0: 50 devices (5%)
└── v1.3.0: 5 devices (OUTDATED!)

What's Next

Now that you understand edge architecture: - Architecture - How edge fits into overall Ruvon architecture - State Management - Offline state persistence - Performance - Edge device performance characteristics