Or: What happens when “fast enough” isn’t
318 requests per second. 1,000 concurrent users. Zero dropped connections.
Those are stress test results from Doppar, a PHP framework you probably haven’t heard of. Laravel optimizes for developer experience. Symfony optimizes for enterprise stability. Doppar optimizes for raw speed — and lets you handle the rest.
Who this is for: You’ve profiled your PHP application, optimized your
queries, added caching, and still need more throughput. You’re comfortable
writing integrations that would be a composer require elsewhere. You want
Laravel-like syntax without Laravel-like overhead.
What Is Doppar?
Permalink to "What Is Doppar?"Doppar is a high-performance, minimalist PHP framework that launched version 3.x in late 2025. It’s built on three principles:
- Zero external dependencies for core features
- Intelligent memoization of repeated executions
- Attribute-first configuration
composer create-project doppar/doppar my-app
cd my-app
php pool server:start
Your first route:
// app/Http/Controllers/HelloController.php
#[Mapper(prefix: 'api')]
class HelloController extends Controller
{
#[Route(uri: 'hello/{name}', methods: ['GET'])]
public function greet(string $name): Response
{
return response()->json(['message' => "Hello, {$name}!"]);
}
}
Requirements: PHP 8.3+ and Composer.
History & Philosophy
Permalink to "History & Philosophy"Doppar was created by techmahedy, a developer who wanted Laravel’s elegant syntax without the overhead. The 3.x release in late 2025 marked its transition from experiment to usable framework. It draws a parallel to Laravel’s own origin story — Symfony existed and was robust, yet Laravel found its voice by offering something different.
The philosophy is simple:
“Need a feature? Install and use it. Don’t need it? Keep your application as simple and clean as possible.”
Doppar isn’t trying to replace Laravel or Symfony. It’s an alternative for developers who’ve squeezed every optimization out of their current stack and still need more.
Why Is It Fast?
Permalink to "Why Is It Fast?"Three techniques make Doppar faster than typical PHP frameworks:
1. Intelligent Memoization
Permalink to "1. Intelligent Memoization"Repeated executions are cached automatically. Configuration parsing, service resolution, route matching — anything that runs more than once gets memoized without manual intervention.
2. Zero-Dependency Core
Permalink to "2. Zero-Dependency Core"The ORM, validation, WebSocket server, and scheduler are built into the core. No Doctrine. No external queue packages. No third-party HTTP clients for internal operations. Fewer packages means fewer autoload calls and less initialization overhead.
3. Minimal Boot Tax
Permalink to "3. Minimal Boot Tax"Heavy frameworks pay a “boot tax” — the time spent bootstrapping before handling a single request. Doppar minimizes this by lazy-loading services and avoiding deep dependency chains. In worker mode, the application boots once and stays in memory.
The result: benchmarks show roughly 7-8x higher throughput than typical PHP frameworks under comparable conditions.
Benchmark methodology: The 318 req/s figure comes from
Doppar’s stress test documentation
using wrk with 1,000 concurrent connections over 30 seconds. The “7-8x”
comparison is against a default Laravel installation on the same hardware. These
are vendor-provided numbers — independent benchmarks are welcome.
Deployment model: Doppar runs in two modes. Traditional PHP-FPM works but
loses the performance benefits — each request bootstraps fresh. Worker mode
(php pool server:start) keeps the application in memory between requests,
similar to Swoole or RoadRunner. (For background on these async runtimes, see
Async PHP in Production.) The
benchmarks assume worker mode. If your hosting requires PHP-FPM (shared hosting,
some PaaS), the speed advantage shrinks significantly.
Unique Features
Permalink to "Unique Features"Before comparing individual modules, here’s what Doppar offers that Laravel and Symfony don’t have built-in:
Airbend: Native WebSockets
Permalink to "Airbend: Native WebSockets"Most PHP frameworks treat WebSockets as an afterthought — use Pusher, run a Node.js server, or configure Ratchet. Symfony has Mercure, which solves real-time elegantly but requires a separate hub service (written in Go). Laravel offers Broadcasting with Pusher or a self-hosted solution via Laravel Reverb.
Doppar takes a different approach with Airbend — a native WebSocket component that runs in the same PHP process:
use Doppar\Airbend\Broadcast;
Broadcast::channel('orders')
->event('order.created')
->data(['order_id' => $order->id])
->send();
// Channel authorization
Broadcast::channel('orders.{id}', function ($user, $id) {
return $user->orders()->where('id', $id)->exists();
});
No external services. No separate server process. The trade-off: Mercure is battle-tested and scales horizontally; Airbend is newer and ties your WebSockets to your PHP worker’s lifecycle.
Dual-Mode Task Scheduler
Permalink to "Dual-Mode Task Scheduler"Standard cron-triggered mode:
* * * * * cd /path/to/project && php pool schedule:run
Or daemon mode for sub-second precision:
php pool schedule:daemon
Daemon mode runs continuously, checking tasks multiple times per second — no Supervisor configuration required.
Schedule::call(fn() => $this->pingHealthCheck())
->everySecond();
Schedule::command('reports:generate')
->dailyAt('02:00')
->runInBackground();
Automatic Transactions via Attributes
Permalink to "Automatic Transactions via Attributes"use Phaseolies\Utilities\Attributes\Transaction;
#[Transaction]
public function transferFunds(Account $from, Account $to, float $amount): void
{
$from->decrement('balance', $amount);
$to->increment('balance', $amount);
// Commits on success, rolls back on exception
}
Optional AI Integration
Permalink to "Optional AI Integration"Doppar includes an AI wrapper — not a core dependency, but available if you need it:
use Doppar\AI\Agent;
$response = Agent::make()
->model('gpt-4')
->prompt('Summarize this order')
->context(['order' => $order->toArray()])
->send();
Supported providers: OpenAI (GPT-3.5/4), Anthropic (Claude), and local models
via TransformersPHP. You configure API keys in .env — no AI calls happen
unless you explicitly use the Agent class.
Module Comparisons
Permalink to "Module Comparisons"Routing
Permalink to "Routing"Doppar — Attributes with inline rate limiting:
#[Mapper(prefix: 'api/users', middleware: ['auth'])]
class UserController extends Controller
{
#[Route(uri: '{id}', methods: ['GET'], name: 'users.show')]
public function show(string $id): Response
{
return response()->json(User::find($id));
}
#[Route(uri: '', methods: ['POST'], rateLimit: 10, rateLimitDecay: 1)]
public function store(Request $request): Response
{
// Limited to 10 requests per minute
}
}
Symfony — Native attributes, rate limiting via separate bundle:
#[Route('/api/users', name: 'users_')]
class UserController extends AbstractController
{
#[Route('/{id}', name: 'show', methods: ['GET'])]
public function show(int $id): Response
{
return $this->json($this->userRepository->find($id));
}
}
Laravel — File-based routing (attributes via package):
// routes/api.php
Route::middleware(['auth:sanctum'])->prefix('api/users')->group(function () {
Route::get('{id}', [UserController::class, 'show']);
Route::post('', [UserController::class, 'store'])->middleware('throttle:10,1');
});
Dependency Injection
Permalink to "Dependency Injection"Doppar — Explicit binding at parameter level:
class OrderController extends Controller
{
#[Route(uri: 'orders', methods: ['POST'])]
public function store(
#[Bind(StripeGateway::class)] PaymentGatewayInterface $gateway,
Request $request
): Response {
// $gateway is StripeGateway
}
}
Symfony — Config file or #[Autowire]:
// config/services.yaml
services:
App\Payment\PaymentGatewayInterface:
class: App\Payment\StripeGateway
Laravel — Service provider:
// AppServiceProvider.php
$this->app->bind(PaymentGatewayInterface::class, StripeGateway::class);
Doppar’s approach makes the binding visible at the call site. Trade-off: more verbose when you want framework-wide defaults.
ORM
Permalink to "ORM"Doppar — Eloquent-style API, zero dependencies:
$users = User::where('active', true)
->whereBetween('created_at', [$start, $end])
->orderBy('name')
->limit(10)
->get();
// Batch insert with chunking
User::saveMany($records, 1000);
// Memory-efficient iteration
foreach (User::where('active', true)->cursor() as $user) {
// One record at a time
}
Symfony (Doctrine) — QueryBuilder:
$users = $this->userRepository->createQueryBuilder('u')
->where('u.active = :active')
->andWhere('u.createdAt BETWEEN :start AND :end')
->orderBy('u.name')
->setMaxResults(10)
->setParameters(['active' => true, 'start' => $start, 'end' => $end])
->getQuery()
->getResult();
Laravel (Eloquent) — Nearly identical to Doppar:
$users = User::where('active', true)
->whereBetween('created_at', [$start, $end])
->orderBy('name')
->limit(10)
->get();
Doppar’s ORM syntax mirrors Eloquent — familiar if you’re coming from Laravel. The difference: no external package, built into core.
Validation
Permalink to "Validation"Doppar:
$validated = $request->sanitize([
'name' => 'required|min:2|max:100',
'email' => 'required|email|unique:users',
'age' => 'required|int|between:18,120',
]);
Symfony:
class UserDto
{
#[Assert\NotBlank]
#[Assert\Length(min: 2, max: 100)]
public string $name;
#[Assert\Email]
public string $email;
}
$errors = $validator->validate($dto);
Laravel:
$validated = $request->validate([
'name' => 'required|min:2|max:100',
'email' => 'required|email|unique:users',
]);
Doppar and Laravel are nearly identical. Symfony’s DTO approach offers better type safety for complex domains but requires more code.
Community & Ecosystem
Permalink to "Community & Ecosystem"| Metric | Doppar | Laravel | Symfony |
|---|---|---|---|
| GitHub Stars | ~200* | 78k+ | 30k+ |
| First Release | 2024 | 2011 | 2005 |
| Packagist Downloads | <10k* | 300M+ | 500M+ |
| Discord/Community | Small* | 120k+ | Large |
*Doppar figures are estimates as of January 2026. Check GitHub and Packagist for current numbers.
Doppar’s ecosystem is young. You’ll write integrations that would be a
composer require in Laravel or Symfony. The trade-off for performance is doing
more yourself.
Should You Use Doppar?
Permalink to "Should You Use Doppar?"The honest answer: probably not — yet.
Doppar makes sense in a narrow scenario: you’re building high-throughput APIs, you’ve profiled your Laravel or Symfony app to death, and you’re still bottlenecked by framework overhead. You’re comfortable writing integrations yourself, and you don’t need PostgreSQL (MySQL and SQLite only). If that’s you, Doppar is worth a serious look.
For everyone else, the trade-offs are hard to justify. Laravel has thousands of packages and a massive community. Symfony powers enterprise systems with battle-tested stability. Both have weathered a decade of production edge cases, security audits, CVE tracking, and responsible disclosure processes. Doppar hasn’t seen that volume of real-world usage yet — some documentation pages still return 404, and the queue system isn’t fully documented.
There are also risks to consider. Doppar has a single primary maintainer. If techmahedy steps away, the project’s future is uncertain. The framework is young — expect breaking changes between minor versions as APIs mature. And hiring developers with Doppar experience will be significantly harder than Laravel or Symfony.
If you need raw performance but don’t want to abandon the ecosystem, consider Swoole or RoadRunner on top of Laravel or Symfony. You’ll get most of the performance gains while keeping access to packages, documentation, and community support.
For a deeper Laravel vs Symfony comparison without the performance angle, see Laravel vs Symfony 2025: When to Use Which.
Doppar isn’t a Laravel replacement. It’s a specialized tool for a specific problem.
My take: Doppar is an interesting project worth watching. The philosophy is sound — Laravel-like ergonomics without the overhead — and the native WebSocket integration is genuinely compelling. But I’m skeptical about production use. The gap to Laravel isn’t wide enough to justify the ecosystem trade-offs for most teams. If you need raw performance, Swoole or RoadRunner on top of Laravel/Symfony might give you 80% of the gains without abandoning the ecosystem. Doppar feels like a framework for a very specific niche: high-throughput APIs where every millisecond matters and you’re comfortable building everything yourself.
That said, competition is healthy. If Doppar pushes Laravel and Symfony to care more about performance, everyone wins. I’ll be keeping an eye on it — but my production apps stay on Symfony for now.
The documentation is at doppar.com. The framework is MIT-licensed on GitHub. PHP 8.3+, Composer, and a willingness to trade convenience for microseconds.
