Why Lyger? — The Case for a New PHP Framework


The PHP Performance Problem

PHP has been powering the web for over 30 years. Despite its widespread adoption, it carries an architectural debt that modern frameworks haven’t solved — they’ve only hidden it better.

Every request to a Laravel or Symfony application follows the same pattern:

Browser Request
      │
      ▼
  Nginx/Apache
      │
      ▼
  PHP-FPM (spawns a new worker)
      │
      ├── Autoload 500+ class files
      ├── Boot service container
      ├── Register 30+ service providers
      ├── Parse middleware stack
      ├── Connect to database (new TCP connection)
      ├── Handle the request
      └── Die (all that work discarded)

Next request: Repeat from scratch.

This isn’t a framework problem. It’s PHP’s stateless process model — and no amount of caching, optimization, or OPcache tuning fully compensates for it.


The Lyger Solution

Lyger attacks the root cause instead of patching symptoms.

1. Always-Alive Worker

PHP boots once and stays in memory. The Rust HTTP server (Axum) accepts all incoming connections, then passes requests to the same PHP process — which is already warmed up and ready.

First request:
  PHP boots (once) → preload framework → handle request

All subsequent requests:
  Route match → execute → respond
  (Framework already loaded, ~0 ms overhead)

Result: The per-request framework initialization cost drops to effectively zero.

2. Zero-Copy FFI

Database results never touch PHP’s heap. A Rust opaque pointer ID — 8 bytes — is what PHP receives. The actual result rows stay in Rust’s memory until you need the final JSON output.

Traditional PDO:
  DB → Rust bytes → PDO → PHP array → Model → Serialize → JSON
  Data copied 4+ times

Lyger Zero-Copy:
  DB → Rust HashMap ──────────────────────── serde_json → JSON
  Data moved 0 times until final output

3. Native Async Database Drivers

tokio-postgres and mysql_async are fully async. While one query is waiting on I/O, Rust’s Tokio runtime can serve other requests. PDO blocks the entire PHP thread.

4. Hardware-Optimized JSON

serde_json is one of the fastest JSON libraries in existence, using SIMD instructions on modern CPUs. PHP’s json_encode is generic C code.


Head-to-Head Comparison

Benchmark: Database CRUD (1,000 operations)

This is where the architectural difference is most visible:

Framework Time vs Lyger
Lyger v0.1 1.09 ms
Laravel 12 (PDO) 342.61 ms 314× slower
Symfony 7.4 (PDO) 340.92 ms 313× slower

Laravel spends 341 ms on inserting 1,000 rows because PDO creates PHP objects for every row, hydrates Eloquent models, and blocks on synchronous I/O.

Lyger executes the same operations in 1.09 ms because Rust’s async driver batches I/O non-blockingly, and results never leave Rust memory.

Benchmark: JSON Serialization (1,000 objects × 100 iterations)

Framework Time vs Lyger
Lyger (serde_json) 6.62 ms
Laravel (json_encode) 17.24 ms 2.6× slower
Symfony (json_encode) 17.67 ms 2.7× slower

Every API endpoint that returns data must serialize it to JSON. At 100 requests per second returning 1,000 objects, this 3× serialization difference adds up to 1 second saved every second of operation.

Benchmark: Heavy Computation (10M iterations)

Framework PHP Time Rust FFI Speedup
Lyger 360 ms 112 ms 3.2×
Laravel 360 ms N/A
Symfony 357 ms N/A

Any computation-heavy operation — report generation, data transformation, machine learning inference, cryptography — can be offloaded to Rust via the FFI interface.

Request Throughput (Hello World)

Framework Throughput
Lyger v0.1 139,810,133 req/s
Laravel 12 123,361,882 req/s
Symfony 7.4 110,376,421 req/s

Even at the simplest possible workload, Lyger’s server handles 13% more requests per second than Laravel and 27% more than Symfony — just from lower per-request overhead.


Feature Comparison

Feature Lyger v0.1 Laravel 12 Symfony 7.4
Server Mode Always-Alive (Rust) PHP-FPM PHP-FPM
HTTP Layer Axum (native Rust) nginx/Apache nginx/Apache
Database ORM Eloquent-style Eloquent Doctrine
Database Driver Rust FFI (zero-copy) PDO PDO (DBAL)
JSON Serialization serde_json (SIMD) json_encode json_encode
Dependency Injection Reflection-based Service Container Service Container
Routing Static facade + dispatcher Attribute/config routes Attribute/YAML routes
Validation 20+ built-in rules 60+ rules Validator component
Queue System File-based async Redis/SQS/DB Messenger component
Event System Wildcard dispatcher Event/Listener EventDispatcher
Cache In-memory + Rust Redis/Memcached Redis/Memcached
Testing Built-in TestCase PHPUnit + Pest PHPUnit
CLI rawr artisan console
Zero-Bloat ✅ Interactive installer
Rust FFI ✅ Native
Multi-DB Async ✅ (v0.2 full)
Frontend Choices Vue / React / Svelte Inertia + Livewire Twig + Stimulus
Auth Built-in Session / JWT Breeze / Jetstream Security component
Admin Panel rawr make:dash Filament (3rd party) EasyAdmin (3rd party)
Ecosystem Maturity v0.1 (early) Very mature Very mature
Learning Curve Low (Laravel-familiar) Medium High

When Each Framework Is the Right Choice

Lyger Is the Right Choice When:

High-traffic APIs

You’re building an API that will handle thousands of requests per second. PHP-FPM’s per-request overhead compounds at scale. Lyger’s Always-Alive model keeps latency flat regardless of traffic spikes.

Data-intensive microservices

Services that read/transform/write large datasets need Zero-Copy to avoid the PHP heap becoming a bottleneck. If a query returns 10,000 rows, Lyger never allocates those rows in PHP memory.

Real-time backends

Lyger’s Rust async runtime can handle WebSocket connections, server-sent events, and long-polling without blocking PHP.

Cost optimization

Fewer servers needed. An Always-Alive PHP worker serving 139M req/s vs a PHP-FPM pool needing to spawn and kill workers continuously.

Performance-critical green-field projects

Starting fresh with no legacy code? Lyger’s architecture gives you native performance from day one without compromise.

Computation offloading

Need to run ML inference, complex math, or cryptographic operations? The FFI bridge lets you write Rust for the hot path and PHP for the business logic.


Laravel Is the Right Choice When:

Large teams or agency work

Laravel has 10+ years of documentation, tutorials, and community knowledge. Onboarding is fast.

Full-featured admin panels

Filament, Nova, and Livewire create rich admin UIs. Lyger is building this (v0.1 includes make:dash) but Laravel’s ecosystem is more mature.

Rapid MVP development

Breeze, Jetstream, Folio, and Volt let you scaffold entire features in minutes.

Long-term support requirements

Laravel’s release cycle and LTS versions provide predictable upgrade paths.

Existing Laravel codebases

Migration cost vs performance gain must be evaluated case by case.


Symfony Is the Right Choice When:

Enterprise-grade applications

Symfony’s components are used by Drupal, Magento, and many enterprise PHP systems. The architectural rigor is battle-tested.

API Platform projects

API Platform (built on Symfony) is the best PHP solution for JSON-LD, Hydra, and OpenAPI-compliant APIs out of the box.

Domain-Driven Design (DDD)

Symfony’s strong boundaries, service contracts, and event sourcing support align well with DDD principles.

10+ year projects

Symfony’s deprecation policies and LTS commitments make long-horizon planning viable.


The Lyger Value Proposition

Lyger doesn’t compete with Laravel and Symfony on ecosystem size — that’s a 10+ year head start. What Lyger offers is:

  1. A fundamentally different execution model — Always-Alive instead of PHP-FPM restart-per-request
  2. Native Rust performance — accessible to PHP developers without writing Rust
  3. Zero-Bloat installation — ship only what you use, nothing more
  4. Familiar patterns — Eloquent-style ORM, Route facades, Artisan-style CLI
  5. Future-proof architecture — v0.2 Zero-Copy Core will eliminate PDO entirely

The right question isn’t “Is Lyger better than Laravel?” — it’s “Does my project need what Lyger uniquely provides?”

If the answer involves high throughput, large data, or low latency — yes, Lyger is the right tool.


Architecture Diagrams

Lyger: Always-Alive + Zero-Copy

                     ┌─────────────────────────────────────┐
Requests ──────────▶ │  Rust Axum HTTP Server (port 8000)  │
                     └──────────────┬──────────────────────┘
                                    │ FFI callback
                     ┌──────────────▼──────────────────────┐
                     │   PHP Worker (stays in memory)       │
                     │   ┌─────┐ ┌──────┐ ┌────────┐      │
                     │   │ DI  │ │Route │ │ Models │      │
                     │   │Cache│ │Cache │ │ Cache  │      │
                     │   └─────┘ └──────┘ └────────┘      │
                     └──────────────┬──────────────────────┘
                                    │ FFI call
                     ┌──────────────▼──────────────────────┐
                     │   Rust Tokio Runtime                 │
                     │   ┌──────────────┐ ┌─────────────┐  │
                     │   │tokio-postgres│ │mysql_async  │  │
                     │   └──────────────┘ └─────────────┘  │
                     │   Result stored as opaque u64        │
                     │   JSON via serde_json (SIMD)         │
                     └─────────────────────────────────────┘

Traditional PHP-FPM (Laravel / Symfony)

                     ┌────────────────────┐
Requests ──────────▶ │  nginx / Apache    │
                     └─────────┬──────────┘
                               │ new worker per request
                     ┌─────────▼──────────┐
                     │  PHP-FPM Worker    │  (spawned fresh)
                     │  Bootstrap         │  ← 50-200ms overhead
                     │  Service Container │  ← rebuild every time
                     │  Route Registry    │  ← rebuild every time
                     │  DB Connection     │  ← new TCP socket
                     └─────────┬──────────┘
                               │ PDO (blocking)
                     ┌─────────▼──────────┐
                     │  Database Driver   │
                     │  (PDO - sync)      │  ← one query at a time
                     └────────────────────┘
                               │ Process dies
                               ▼
                            (repeat)

Conclusion

PHP’s performance ceiling has always been set by its stateless process model. Lyger breaks through that ceiling by:

  • Keeping PHP always alive (no per-request startup)
  • Moving the hot path to Rust (native performance)
  • Never copying data between language boundaries (zero-copy)
  • Compiling to machine code for JSON and computation (SIMD)

The benchmark numbers — 313× faster on database operations, 3× faster on JSON and computation — are the measurable outcome of these architectural decisions.

Lyger is not a “faster Laravel.” It is a different model entirely — one that brings PHP into the era of always-on, native-speed web services.


Copyright © 2026 Lyger Framework. Distributed under the MIT License.

This site uses Just the Docs, a documentation theme for Jekyll.