Skip to content

Architecture Explanation ​

Nexphant is split into small runtime packages, with nexphant/framework acting as the application-facing meta-package. An application starts from Nexphant\App, but the request path is handled by the server, runtime, core safety primitives, lifecycle ownership, support configuration, and optional feature packages.

mermaid
flowchart TD
    App["Nexphant\\App"]
    Framework["nexphant/framework<br/>routes, middleware, attributes, app bootstrap"]
    Server["nexphant/server<br/>sockets, HTTP parsing, router dispatch, WebSocket, SSE"]
    Runtime["nexphant/runtime<br/>event loop selection, workers, timers, channels, drain"]
    Core["nexphant/core<br/>context, cancellation, ownership, resource registry"]
    Support["nexphant/support<br/>config, env, cache helpers, extension detection"]

    App --> Framework
    Framework --> Server
    Server --> Runtime
    Runtime --> Core
    Core --> Support

Feature packages attach to this stack instead of replacing it:

PackageRole
nexphant/databaseQuery builder, drivers, pooling helpers, migrations, cache, and query metrics.
nexphant/queueBackground jobs, drivers, retries, workers, queue metrics, and coroutine consumers.
nexphant/schedulerTimer-based scheduled task runtime.
nexphant/cacheArray, APCu, and Redis cache stores plus cache warming.
nexphant/viewLightweight Blade-like templates and view responses.
nexphant/observabilityRuntime state, metrics, logging, health checks, dashboards, and leak reporting.
nexphant/consoleRuntime, queue, optimize, preload, and diagnostic CLI commands.
nexphant/devFile watching and reload tooling for development.
nexphant/lifecycleStructured owner scopes and resource cleanup discipline.

Boot Flow ​

App::create() stores the initial config, applies support-level runtime flags, resolves the runtime profile, creates the router, and delays expensive server boot work until listen().

mermaid
flowchart TD
    Create["App::create($config)"]
    Apply["Support\\RuntimeConfig::apply($config)"]
    Resolve["RuntimeConfigResolver::resolve($config)"]
    Router["Create Router"]
    DB["Apply DB cache and coalesce toggles"]
    Listen["listen($port, $host)"]
    Env["Load .env and config/app.php"]
    Warm["Warm optimized classes and compiled hot paths"]
    Merge["Merge normalized server config and runtime profile"]
    HttpServer["Create or configure HttpServer"]
    Handlers["Register not-found and router dispatch handlers"]
    Start{"workers > 1 and supervisor enabled?"}
    Single["Start single worker"]
    Supervisor["Start supervisor-managed workers"]

    Create --> Apply --> Resolve --> Router --> DB --> Listen
    Listen --> Env --> Warm --> Merge --> HttpServer --> Handlers --> Start
    Start -- "No" --> Single
    Start -- "Yes" --> Supervisor

This split keeps configuration cheap and predictable. The application can define routes, middleware, static files, WebSocket handlers, SSE endpoints, telemetry endpoints, and runtime tuning before sockets start accepting traffic.

Runtime Profiles ​

The runtime resolver converts app config into concrete server settings. runtime_mode chooses a profile:

ModeIntent
autoUses native event extensions when available, otherwise balanced defaults.
low_latencyLower keep-alive timeout and leaner metrics for native event-loop deployments.
balancedGeneral-purpose defaults with metrics and file stats enabled.
throughputHigher worker and callback limits for heavier sustained traffic.
benchmarkLean profile for repeatable benchmark runs.

event_loop can be auto, event, ev, uv, or select. socket_driver can be auto, native, or stream. Auto mode prefers native extensions when installed and falls back to portable PHP implementations.

Request Path ​

An HTTP request moves through the stack in this order:

mermaid
sequenceDiagram
    participant Client
    participant Socket as Socket Accept
    participant Parser as HttpParser / FastPathEngine
    participant ReqRes as ServerRequest + ServerResponse
    participant Global as Global Middleware
    participant Router as Framework Router
    participant Route as Route Middleware
    participant Handler as User Handler
    participant Writer as Response Writer

    Client->>Socket: HTTP request
    Socket->>Parser: raw bytes
    Parser->>ReqRes: parsed request
    ReqRes->>Global: request + response
    Global->>Router: dispatch
    Router->>Route: matched route
    Route->>Handler: invoke
    Handler->>Writer: return response data
    Writer-->>Client: serialized response
    Writer-->>Socket: keep-alive or close

Framework handlers may return arrays, objects, strings, Nexphant\Server\Response, or Nexphant\Server\RawResponse. Arrays and objects are serialized as JSON. Static routes can be promoted into fast JSON, text, or raw responses so the server can bypass the full framework dispatch path for hot endpoints.

Safety Model ​

Long-running PHP keeps processes alive across requests, so Nexphant separates performance tuning from safety controls.

With runtime_safety enabled, requests use the asynchronous router dispatch path with runtime context, ownership, drain tracking, and lifecycle discipline. Resources can be associated with owners such as workers, requests, fibers, queue jobs, scheduler tasks, connections, and timers.

With performance_mode or runtime_safety: false, Nexphant uses lean defaults and may choose faster synchronous dispatch paths. This is useful for benchmarks or tightly controlled deployments, but applications should only disable safety features when resource lifetimes are already understood.

Worker Lifecycle ​

Nexphant runs as a persistent server, not as PHP-FPM request-per-process code.

  1. The main process boots the app and prepares the HTTP server.
  2. If workers > 1 and supervisor mode is enabled, the supervisor forks workers.
  3. Each worker owns a server loop, accepts sockets, and publishes runtime stats.
  4. On shutdown, workers stop accepting new sockets and wait for in-flight work.
  5. Runtime metadata is written to storage/runtime.pid and storage/runtime.json for CLI inspection.

Queue workers, scheduled tasks, timers, and background fibers live beside HTTP work in the same runtime model. They share the same need for ownership, cancellation, drain behavior, and metrics.

Observability ​

Observability is available at three layers:

  • Application telemetry via $app->runtime('/api'), which exposes live, ready, health, and metrics endpoints.
  • CLI inspection through nexphant/console, including runtime status, health, metrics, workers, queue stats, retries, and optimize commands.
  • Package-level metrics from nexphant/server, nexphant/runtime, nexphant/database, nexphant/queue, and nexphant/observability.

Metrics and tracing can be tuned with metrics, runtime_features, resource_trace, and leak_detection config.

Package Boundaries ​

The package dependency direction is intentional:

mermaid
flowchart BT
    Support["nexphant/support"]
    Core["nexphant/core"]
    Lifecycle["nexphant/lifecycle"]
    Runtime["nexphant/runtime"]
    Server["nexphant/server"]
    Framework["nexphant/framework"]
    Queue["nexphant/queue"]
    Database["nexphant/database"]
    Cache["nexphant/cache"]
    View["nexphant/view"]
    Observability["nexphant/observability"]
    Console["nexphant/console"]
    Dev["nexphant/dev"]

    Core --> Support
    Lifecycle --> Core
    Runtime --> Core
    Runtime --> Lifecycle
    Server --> Runtime
    Server --> Core
    Framework --> Server
    Framework --> Runtime
    Framework --> Core
    Queue --> Runtime
    Queue --> Core
    Database --> Core
    Database --> Support
    Cache --> Core
    Cache --> Support
    View --> Framework
    Observability --> Core
    Observability --> Support
    Console --> Framework
    Console --> Observability
    Dev --> Framework

support provides low-level helpers. core defines runtime safety primitives. runtime orchestrates cooperative execution. server handles protocol and socket work. framework turns those pieces into the developer-facing App. Higher-level packages add capabilities while keeping the runtime-first structure intact.

Released under the MIT License.