Platform.sh is now Upsun. Click here to learn more
Upsun User Documentation

FrankenPHP

FrankenPHP is a modern PHP application server designed as a high-performance alternative to traditional PHP-FPM setups. It combines a native PHP runtime with an HTTP server, reducing orchestration overhead while enabling new execution models that can significantly improve performance.

FrankenPHP is particularly well-suited for modern PHP frameworks and applications that want faster request handling, simpler infrastructure, and optional support for long-running workers.

Why FrankenPHP? Anchor to this heading

Traditional PHP deployments rely on multiple moving parts: a web server, PHP-FPM, and external process management. FrankenPHP simplifies this architecture by embedding PHP execution directly into the server. Some key features include:

  • Faster startup times and reduced per-request overhead compared to PHP-FPM.
  • A modern architecture that works for contemporary PHP runtimes and frameworks.
  • Fewer services to configure and maintain.
  • Support for a worker-based execution model that avoids re-booting the application on every request.

Execution modes Anchor to this heading

FrankenPHP supports two distinct execution modes. Choosing the right mode depends on your application’s architecture and tolerance for stateful execution.

Classic mode Anchor to this heading

Classic mode behaves similarly to PHP-FPM and is the recommended default for most applications.

  • Each request runs in a clean, isolated environment
  • No application state is shared between requests
  • Lifecycle expectations are identical to PHP-FPM
  • Safe for existing PHP applications without modification

In this mode, FrankenPHP provides performance and architectural improvements while preserving the stateless execution model.

Worker mode Anchor to this heading

Worker mode enables long-running PHP worker processes that handle multiple requests over their lifetime.

  • The application is booted once and kept in memory
  • Subsequent requests reuse the already-loaded application
  • Significantly reduced cold-start overhead
  • Higher throughput and faster response times

This mode introduces stateful execution.

Understanding Worker modes Anchor to this heading

Stateless execution (PHP-FPM and Classic mode) Anchor to this heading

In traditional PHP execution models every request starts from a clean slate, the application boots, handles the request, then shuts down and there are no variables, objects, or internal state persist between requests.

This guarantees isolation and predictability, but it comes with unavoidable overhead as the full boot and teardown cycle happens on every request.

Stateful execution (Worker mode) Anchor to this heading

With Stateful execution in Worker mode, the application is booted once. It remains in memory and handles many requests and internal state persists unless explicitly reset. This improves performance dramatically, but introduces new risks. For example, in a stateful environment:

  • Mutated variables may leak into later requests
  • Static properties and singletons persist
  • Cached data may become stale or invalid
  • Connection pools or services may behave unexpectedly

These issues do not occur in stateless PHP-FPM setups.

Observability and profiling Anchor to this heading

FrankenPHP is well supported by Blackfire, making it easy to profile and monitor performance in both Classic and Worker modes.

Configuration Anchor to this heading

FrankenPHP is available as a package in Upsun composable stacks.

Classic mode configuration Anchor to this heading

.upsun/config.yaml
applications:
  app:
    type: "composable:25.11"
    source:
      root: "/"

    stack:
      runtimes:
        - "php@8.4":
            extensions:
              - apcu
              - blackfire
              - ctype
              - iconv
              - mbstring
              - pdo_pgsql
              - sodium
              - xsl
        - "nodejs@22"
      packages:
        - "frankenphp"

    variables:
      php:
        opcache.preload: config/preload.php
      env:
        APP_RUNTIME: 'Runtime\\FrankenPhpSymfony\\Runtime'
        # composer require runtime/frankenphp-symfony

    web:
      upstream:
        socket_family: tcp
        protocol: http

      commands:
        start: frankenphp php-server --listen=localhost:$PORT --root=$PLATFORM_DOCUMENT_ROOT index.php

      locations:
        "/":
          root: "public"
          expires: 1h
          passthru: true
          allow: true
          scripts: true
          request_buffering:
            enabled: false

Worker mode configuration Anchor to this heading

.upsun/config.yaml
applications:
  app:
    type: "composable:25.11"
    source:
      root: "/"

    stack:
      runtimes:
        - "php@8.4":
            extensions:
              - apcu
              - blackfire
              - ctype
              - iconv
              - mbstring
              - pdo_pgsql
              - sodium
              - xsl
        - "nodejs@22"
      packages:
        - "frankenphp"

    variables:
      php:
        opcache.preload: config/preload.php
      env:
        APP_RUNTIME: 'Runtime\\FrankenPhpSymfony\\Runtime'
        # composer require runtime/frankenphp-symfony

    web:
      upstream:
        socket_family: tcp
        protocol: http

      commands:
        start: frankenphp php-server --worker $PLATFORM_DOCUMENT_ROOT/index.php --listen=localhost:$PORT --root=$PLATFORM_DOCUMENT_ROOT

      locations:
        "/":
          root: "public"
          expires: 1h
          passthru: true
          allow: true
          scripts: true
          request_buffering:
            enabled: false

Using the latest FrankenPHP version Anchor to this heading

You can request FrankenPHP from the Nix unstable channel to access the latest available version.

.upsun/config.yaml
stack:
  packages:
    - package: frankenphp
      channel: unstable

Choosing the right mode Anchor to this heading

  • Use Classic mode if you want safety, predictability, and drop-in compatibility with existing PHP applications.
  • Use Worker mode if you need maximum performance and are prepared to manage application state explicitly.

Both modes are fully supported on Upsun, allowing you to choose the execution model that best fits your application.