Skip to main content

Synthetics Architecture

Statux Synthetics is a synthetic monitoring product that provides uptime monitoring and alerting for HTTP/HTTPS endpoints and TCP services.

Overview

The Synthetics API (apps/synthetics/) runs on port 3002 and is available at synthetics-api.statux.io.

Core Concepts

Checks

A Check defines what to monitor and how:

  • Check Types: HTTP, HTTPS, TCP
  • Targets: URLs for HTTP/HTTPS, host:port for TCP
  • Intervals: 30 seconds to 30 minutes
  • Regions: AWS regions for distributed checks
  • Relays: Private agents for internal network monitoring

Relays

Relays are private agents that can be deployed inside your network to monitor internal services:

  • Connect to the API via secure token authentication
  • Poll for assigned checks on a schedule
  • Submit results back to the API
  • Support heartbeat monitoring for connectivity status

Results

Check Results capture execution outcomes:

  • Response time (ms)
  • HTTP status codes
  • TLS certificate info
  • Error messages for failures
  • Execution timestamps

Module Structure

apps/synthetics/src/
├── modules/
│ ├── checks/ # Check CRUD and querying
│ ├── results/ # Check result storage and queries
│ ├── relays/ # Private relay management
│ ├── execution/ # Public check execution engine
│ ├── aggregation/ # Metrics aggregation and S3 archival
│ ├── webhooks/ # Webhook notifications
│ ├── analytics/ # Usage analytics
│ ├── projects/ # Project management
│ ├── organizations/ # Organization management
│ ├── users/ # User access management
│ └── product-access/ # Product subscription access
├── entities/ # TypeORM entities
├── migrations/ # Database migrations
└── main.ts # Application bootstrap

Key Entities

Check Entity

@Entity({ schema: 'synthetics', name: 'checks' })
export class Check extends BaseEntity {
projectId: string;
name: string;
checkType: CheckType; // http, https, tcp
target: string; // URL or host:port
httpMethod: HttpMethod; // GET, POST, HEAD
expectedStatusCode: number;
intervalSeconds: number;
timeoutMs: number;
regions: string[]; // AWS region codes
relayId: string | null; // Private relay assignment
currentStatus: CheckStatus; // up, down, degraded, unknown
consecutiveFailures: number;
failureThreshold: number;
recoveryThreshold: number;
}

Relay Entity

@Entity({ schema: 'synthetics', name: 'relays' })
export class Relay extends BaseEntity {
projectId: string;
name: string;
authToken: string; // Hashed token
authTokenPrefix: string; // First 12 chars for identification
status: RelayStatus; // active, inactive, disconnected
relayVersion: string;
lastHeartbeatAt: Date;
}

API Patterns

Check Lifecycle

  1. Create Check: Validate target format, set default regions
  2. Execution: Either via public regions or private relay
  3. Result Processing: Update check state based on thresholds
  4. Alerting: Fire webhooks on status changes

Relay Authentication

Relays authenticate using bearer tokens:

// Token format: stx_relay_{64_char_hex}
// Stored as SHA-256 hash in database
const rawToken = `stx_relay_${randomBytes(32).toString('hex')}`;
const tokenHash = createHash('sha256').update(rawToken).digest('hex');

The RelayAuthGuard validates tokens and attaches the relay to the request.

Status State Machine

UNKNOWN → UP (on first successful check)
UP → DOWN (after failureThreshold consecutive failures)
DOWN → UP (after recoveryThreshold consecutive successes)
UP/DOWN → DEGRADED (on slow response or partial failure)

Testing

Run tests with:

npm run test:synthetics

Test files are located alongside service files:

  • checks.service.spec.ts
  • relays.service.spec.ts
  • results.service.spec.ts

Database

Uses the synthetics schema in PostgreSQL. All entities follow the snake_case naming convention for database columns.

Key Tables

TablePurpose
projectsProject configuration
checksCheck definitions
check_resultsExecution results
relaysPrivate relay agents
webhook_subscriptionsNotification webhooks
usersProject user access