Skip to main content

Architecture

Understanding Toggly's architecture helps you make informed decisions about how to integrate and use the platform effectively.

High-Level Overview

Toggly uses a dual-architecture approach optimized for different deployment scenarios:

  • Server-side SDKs: Fetch feature definitions and evaluate locally
  • Client-side SDKs: Receive pre-evaluated feature flags
┌────────────────────────────────────────────────────────┐
│ Toggly Service │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Dashboard │ │ Feature │ │ Metrics │ │
│ │ UI │ │ Store │ │ Pipeline │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────────────────────────────────────────┘
│ │
│ │
┌────┴────┐ ┌────┴────┐
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Server │ │ Server │ │ Client │ │ Client │
│ SDK │ │ SDK │ │ SDK │ │ SDK │
│ (.NET) │ │ (PHP) │ │ (JS) │ │(React) │
└─────────┘ └─────────┘ └─────────┘ └─────────┘

Server-Side Architecture

Server-side SDKs (.NET, PHP, Go, etc.) fetch feature definitions and evaluate them locally in your application.

How It Works

  1. Fetch Definitions: SDK fetches feature flag definitions from https://definitions.toggly.io:

    • /definitions/{appKey}/{environment} (unsigned)
    • /definitions-signed/{appKey}/{environment} (signed with ECDSA)
  2. Local Evaluation: SDK evaluates features locally using:

    • Microsoft.FeatureManagement (for .NET)
    • Custom evaluation logic (for other languages)
    • Applies targeting rules, segments, and experiments
  3. Real-Time Updates:

    • Polling every 5 minutes
    • WebSocket connection for instant updates
    • ETag support for efficient updates
  4. Metrics & Statistics:

    • Sends usage statistics via gRPC
    • Sends custom metrics via gRPC
    • Batched every minute
  5. Snapshot Support:

    • Can load cached definitions on startup
    • Supports offline operation
    • Updates snapshots when API is available

Server-Side Data Flow

┌─────────────┐
│ Your Server │
│ Application │
└──────┬──────┘

│ 1. Fetch Definitions

┌─────────────────────────────────────┐
│ TogglyFeatureProvider │
│ - GET definitions.toggly.io/... │
│ - WebSocket for live updates │
│ - ETag for conditional requests │
└──────┬──────────────────────────────┘

│ 2. Store & Cache

┌─────────────────────────────────────┐
│ In-Memory Cache │
│ - Feature definitions │
│ - JWK sets (for signed defs) │
└──────┬──────────────────────────────┘

│ 3. Evaluate Locally

┌─────────────────────────────────────┐
│ IFeatureManager │
│ - Apply targeting rules │
│ - Check segments │
│ - Evaluate experiments │
└──────┬──────────────────────────────┘

│ 4. Return Result

┌─────────────┐
│ Your Code │
│ if (feature)│
└─────────────┘

│ 5. Send Metrics

┌─────────────────────────────────────┐
│ gRPC Services │
│ - Usage statistics │
│ - Custom metrics │
└─────────────────────────────────────┘

Client-Side Architecture

Client-side SDKs (JavaScript, React, Vue, Angular, Flutter, etc.) receive pre-evaluated feature flags. You can fetch these flags from two sources:

  1. Toggly Definitions Worker: Direct connection to definitions.toggly.io.
  2. Your Backend Application: Proxy flags through your own server.

Option 1: Fetching from Toggly API

The standard approach connects directly to the definitions worker.

  1. Fetch pre-evaluated signed flags: SDK fetches boolean flags from:
    • https://definitions.toggly.io/evaluated-signed/{appKey}/{environment} (signed booleans)
    • https://definitions.toggly.io/evaluated-variants-signed/{appKey}/{environment} (when variants are enabled)
    • Optional: Include user identity as query parameter (?u=identity or ?userId=identity)
  2. No raw definitions on device: Flags are evaluated on the worker; the client receives booleans (and optional signatures).
  3. Caching: Remote flags are cached in memory / storage for fast access.
  4. Device-local post-filter (optional): Apps may AND worker booleans with local prerequisites at read time — see Post-filter gates.

Serving feature flags from your own backend application is often the ideal approach because it guarantees synchronization between your backend and frontend states.

How it works:

  1. Backend Evaluation: Your server-side application (already using Toggly SDK) evaluates all feature flags for the current request context.
  2. API Endpoint: Your backend exposes the evaluated results (e.g., via a bootstrapped global variable or an API endpoint).
  3. Frontend Usage: The client-side SDK is initialized with these pre-evaluated flags instead of fetching them from Toggly's CDN.

Benefits:

  • Consistency: Frontend and backend rely on the exact same evaluation for a given request.
  • Efficiency: No extra HTTP request needed if flags are injected into the initial HTML response.
  • Security: You have complete control over which flags are exposed to the client.

Client-Side Data Flow (Direct)

┌─────────────┐
│ Browser │
│ Application │
└──────┬──────┘

│ 1. Fetch Flags

┌─────────────────────────────────────┐
│ Toggly Client SDK │
│ - GET definitions.toggly.io/... │
│ - evaluated-signed (+ optional sig)│
│ - Optional local post-filter read │
└──────┬──────────────────────────────┘

│ 2. Receive Pre-Evaluated Flags

┌─────────────────────────────────────┐
│ Toggly Service │
│ - Evaluates features server-side │
│ - Returns boolean flags │
│ - { "feature-key": true } │
└──────┬──────────────────────────────┘

│ 3. Cache & Return

┌─────────────────────────────────────┐
│ Local Cache │
│ - In-memory storage │
│ - 3-minute refresh interval │
└──────┬──────────────────────────────┘

│ 4. Use Flags

┌─────────────┐
│ Your Code │
│ if (flags. │
│ feature) │
└─────────────┘

Key Differences

AspectServer-Side SDKsClient-Side SDKs
Endpointdefinitions.toggly.io/definitions/{appKey}/{environment}definitions.toggly.io/evaluated-signed/{appKey}/{environment}
ResponseFeature definitions (rules, filters)Pre-evaluated boolean flags
EvaluationLocal (in your application)Server-side (by Toggly)
Update MethodPolling (5 min) + WebSocketPolling (5 min) + WebSocket
MetricsgRPC (usage stats, custom metrics)None (optional via separate API)
SecuritySupports signed definitions (ECDSA)Supports signed definitions (ECDSA)
Offline SupportSnapshot providersCached flags + defaults
User ContextFull context for targetingOptional identity parameter

Communication Protocols

HTTP REST API

Server-Side (https://definitions.toggly.io):

  • GET /definitions/{appKey}/{environment} - Get feature definitions (unsigned)
  • GET /definitions-signed/{appKey}/{environment} - Get signed feature definitions
  • GET /.well-known/jwks - Get JSON Web Key Set

Client-Side (https://definitions.toggly.io):

  • GET /evaluated-signed/{appKey}/{environment} - Get signed pre-evaluated flags
  • GET /evaluated-variants-signed/{appKey}/{environment} - Get signed flags with variants (when enabled)
  • Optional: ?u={identity} (or ?userId=) - Include user identity

WebSocket

Client-side and server-side SDKs use WebSocket on the definitions worker for real-time sync signals:

wss://definitions.toggly.io/{appKey}/ws?rev={cachedRevision}

Protocol (client-side SDKs):

  1. Connect with optional ?rev= (cached definitions revision from last fetch)
  2. Receive { type: "sync", etag, lastUpdated, unchanged? } on connect
  3. Skip HTTP fetch when unchanged: true
  4. On { type: "flags-updated", etag, lastUpdated }, fetch only if revision differs
  5. On { type: "signing-key-updated", kid, lastUpdated }, refetch JWKS and definitions

See WebSocket sync for the full client protocol.

Server-side (.NET and similar): connect to the same definitions worker WebSocket; update signals trigger a definitions refresh.

gRPC

Server-side SDKs use gRPC for high-performance metrics:

  • Usage.UsageClient: Sends feature usage statistics
  • Metrics.MetricsClient: Sends custom experiment metrics
  • Batched and sent every minute
  • Automatic retry with exponential backoff

Data Flow

Server-Side Feature Evaluation

  1. Initial Load: SDK fetches definitions from https://definitions.toggly.io/definitions/{appKey}/{environment}
  2. Cache: Definitions cached in memory
  3. Evaluation: When your code checks a feature, SDK evaluates locally:
    • Applies targeting rules
    • Checks user segments
    • Evaluates experiments
    • Returns boolean result
  4. Updates: WebSocket or polling keeps definitions fresh
  5. Metrics: Usage and metrics sent via gRPC

Client-Side Feature Check

  1. Initial Load: SDK fetches flags from https://definitions.toggly.io/evaluated-signed/{appKey}/{environment}
  2. Cache: Flags and definitions revision cached in memory (and optionally persistent storage)
  3. Check: Your code reads boolean value directly
  4. Refresh: WebSocket sync signals + interval polling; HTTP uses If-None-Match for 304 responses
  5. Fallback: Uses cached flags or defaults on error

Feature Flag Update

  1. Dashboard Change: Admin updates feature flag in dashboard
  2. Storage: Change stored in Feature Store
  3. Server-Side: WebSocket notifies SDKs, or polling picks up change
  4. Client-Side: WebSocket flags-updated (with revision) or next poll fetches updated flags; HTTP returns 304 when unchanged
  5. Cache Update: SDK caches updated values
  6. Audit: Change recorded in audit log

Security & Compliance

Privacy by Design

Toggly is designed to minimize data collection and ensure end-user privacy:

  • Aggregated Metrics: Feature usage stats (total requests, unique users) are aggregated locally in your application (server-side SDKs) or in the hosted Toggly Clients app (for client-side SDKs).
  • No PII Collection: We only receive aggregated counts and hashed identifiers for statistical purposes. We do not collect or store raw end-user data or PII (Personally Identifiable Information) from your application traffic.
  • Targeting Data: While you can define user segments with specific attributes (e.g., email, plan, country) for targeting purposes, this data is strictly used for evaluating feature flags in real-time and is not harvested, sold, or used for any other purpose.

Data Encryption

  • All API communication uses TLS 1.3
  • Server-side definitions can be signed with ECDSA (ES256)
  • Feature flag configurations are encrypted in transit and at rest

Authentication & Authorization

  • App Keys: Public keys for both server-side and client-side SDKs
    • Server-side: Used to fetch definitions
    • Client-side: Used to fetch pre-evaluated flags (read-only, safe for frontend)
  • Signed Definitions: Server-side SDKs can verify definitions using JWK sets
  • Key Whitelisting: Optional whitelist of allowed key IDs for enhanced security
  • SSO/SAML: Enterprise customers can use single sign-on
  • SCIM: Automated user provisioning for enterprise

Audit & Compliance

  • All changes are logged with full audit trails
  • User actions are tracked with timestamps and user IDs
  • Compliance with SOC 2 Type II, ISO 27001, and GDPR
  • Data retention policies configurable per organization
  • Right to erasure and data portability support

Performance Optimizations

  • In-Memory Caching: Feature definitions cached locally
  • ETag Support: Single definitions revision on HTTP (If-None-Match, X-Definitions-Revision) and WebSocket (?rev=, sync)
  • Snapshot Providers: Fast startup with cached definitions
  • WebSocket Updates: Instant updates without polling delay
  • Batched Metrics: Usage stats and metrics batched every minute

Client-Side SDKs

  • Lightweight: Receives simple boolean flags (no evaluation overhead)
  • Efficient Caching: Flags cached in memory with configurable refresh
  • Fast Response: Pre-evaluated flags reduce latency
  • Graceful Degradation: Falls back to cached flags or defaults on error

Scalability

Toggly is designed to handle:

  • High throughput: Millions of evaluations per second
  • Global scale: Low latency worldwide via CDN for client-side SDKs
  • High availability: 99.99% uptime SLA
  • Auto-scaling: Automatic scaling based on load
  • Distributed Evaluation: Server-side SDKs evaluate locally, reducing API load

Regional Deployment

Toggly supports regional deployments for:

  • Data residency: Keep data in specific regions
  • Compliance: Meet regional data protection requirements
  • Performance: Lower latency for regional users

Choosing the Right SDK

Use Server-Side SDKs When:

  • You need complex targeting rules evaluated in your backend
  • You want to track detailed usage statistics and metrics
  • You need offline support with snapshot providers
  • You require signed definitions for security
  • You want real-time updates via WebSocket

Use Client-Side SDKs When:

  • You're building a frontend application (web, mobile)
  • You want lightweight, fast flag checks
  • You want to track detailed usage statistics and metrics (same as server-side)

Next Steps