The Laravel developer experience, compiled to a single native binary.
Routes, form requests, an Eloquent-style ORM, Sanctum tokens, queues and a scheduler, in Dart. The server is one ahead-of-time compiled executable that uses every core, and it runs next to your Laravel application on the same database.
Laravel
Route::post('/posts', [PostController::class, 'store'])
->middleware('auth:sanctum');
public function store(StorePostRequest $request)
{
$post = Post::create($request->validated());
return new PostResource($post);
}Daravel
router.post('/posts', posts.store)
.middleware(const ['auth'])
.validates(const StorePostRequest())
.returns(PostResource.schema, name: 'Post');
Future<Object?> store(Request request) async {
final post = await Post.create(request.validated().toMap());
return PostResource(post);
}The form request runs before the handler, answers 403 or 422 in Laravel’s format, and the same declaration documents the route in OpenAPI.
Laravel
$users = User::with('posts')
->withCount('posts')
->where('active', true)
->paginate();
$user->roles()->sync([2, 3]);Daravel
final users = await User.query()
.with_(['posts'])
.withCount('posts')
.where('active', true)
.paginate();
await user.sync('roles', [2, 3]);The same query builder, eager loading and pagination JSON. with is a reserved word in Dart, hence with_.
Laravel
DB::transaction(function () use ($data) {
$order = Order::create($data);
// Dispatched after the commit.
SendReceipt::dispatch($order);
});Daravel
await DB.transaction(() async {
final order = await Order.create(data);
// Dispatched after the commit.
await Queue.dispatch(SendReceipt(order.id));
});Transactions follow the request’s zone: nested calls become savepoints, and jobs wait for the outer commit or are dropped on rollback.
Laravel
$stats = Cache::remember('stats', 60, fn () => Stats::compute());
Cache::lock('report')->block(5, fn () => Report::build());
Route::get('/search', SearchController::class)
->middleware('throttle:60,1');Daravel
final stats = await Cache.remember(
'stats', const Duration(minutes: 1), () => Stats.compute());
await Cache.lock('report')
.block(const Duration(seconds: 5), () => Report.build());
router.get('/search', search.index)
.middleware(const ['throttle:60,1']);With several worker isolates, locks, the process cache and rate limits are kept by a coordinator isolate: 60 per minute means 60 for the whole server, without Redis.
Laravel
Queue::fake();
$this->actingAs($user)
->postJson('/api/posts', ['title' => 'Hello'])
->assertCreated()
->assertJsonPath('data.title', 'Hello');
Queue::assertPushed(PublishPost::class);Daravel
final queue = Queue.fake();
(await client.actingAs(user)
.post('/api/posts', json: {'title': 'Hello'}))
.assertCreated()
.assertJsonPath('data.title', 'Hello');
queue.assertPushed<PublishPost>();Feature tests run the real kernel in memory, roll the database back after each test, and fake queues, events, storage, HTTP and time.
What you get from Dart without losing Laravel
Every point links to the chapter that explains it, and each is checked by the test suite.
- One native bundle
- The application compiles ahead of time into machine code, with SQLite bundled. The server needs no SDK, runtime or source code.
- No reflection, no build step
- Generators write plain Dart into explicit registries, so the compiler sees exactly the code you read.
- Every core on one port
- A supervisor runs worker isolates, respawns crashes and drains on SIGTERM; a coordinator keeps locks and rate limits correct across them.
- Request state stays in its request
- Each request, job and command runs in its own zone, so facades and transactions never leak into another request.
- Next to Laravel, on the same database
- Tokens, bcrypt hashes, Crypt payloads, error JSON and shared tables are Laravel 12’s. Move one endpoint at a time.
- Routes that document themselves
- Declared validation and responses answer 403 and 422 before your handler and generate OpenAPI 3.1.
- Guard rails included
- Hashing off the event loop, lints against SQL interpolation, and security and Laravel conformance suites in CI.
Measured, not claimed
The benchmark harness builds the servers ahead of time and runs them next to a plain dart:io server on the same machine.
GitHub Actions Linux runner, 4 CPUs, benchmark run 40092549095. Method and every scenario: Performance.
Packages
Published together on pub.dev under one version.
| daravel | The framework. |
| dartisan_cli | Projects, generators, hot reload, migrations, native builds. |
| daravel_test | TestClient, database helpers, fakes, Laravel conformance matchers. |
| daravel_lints | Lint rules for Daravel applications. |
| daravel_horizon, daravel_socialite, daravel_reverb | Queue dashboard, OAuth sign-in, WebSockets. (Planned) |
| daragic | Laravel ⇄ Daravel project generator. (Planned) |