Skip to content

Latest commit

 

History

History
414 lines (333 loc) · 20.8 KB

File metadata and controls

414 lines (333 loc) · 20.8 KB

lagodev vs Laravel, Django, NestJS, Express

A senior-level, deliberately honest comparison. lagodev is a young framework with an unusually wide surface area for its age; Laravel and Django are fifteen-plus-year-old ecosystems. This document tells you where lagodev is genuinely competitive, where it wins on first principles (compiled Go, static typing, single-binary deploy), and where the incumbents are simply ahead on maturity, ecosystem, and breadth of third-party packages.

If a row below makes lagodev look universally superior, distrust it. Read the deep-dives and the When NOT to choose lagodev section before betting a project on it.

Performance claims here are qualitative. For measured numbers see BENCHMARKS.md and the runnable suite in benchmarks/. We do not quote invented figures.


Philosophy

Each of these frameworks encodes a different bet about where the cost of software lives.

  • Laravel bets on developer happiness and ecosystem. PHP's request-per- process model means you rarely think about concurrency; the framework and its first-party constellation (Horizon, Sanctum, Cashier, Nova, Octane, Forge, Vapor) cover almost everything a SaaS needs. The cost is runtime: an interpreted language and a per-request bootstrap.

  • Django bets on batteries-included correctness. The ORM, admin, auth, and migrations are tightly integrated and battle-tested over a decade and a half. "The Django way" is opinionated and productive. The cost is the GIL, interpreter overhead, and an ORM that fights you when you outgrow its assumptions.

  • NestJS bets on architecture. It brings Angular-style DI, modules, and decorators to Node, with first-class TypeScript. You get structure and type hints, but the types are erased at runtime, and you inherit Node's single-threaded event loop and the npm dependency surface.

  • Express bets on nothing. It is a minimal router + middleware library. Everything else — ORM, validation, auth, jobs — is something you assemble from npm. Maximum flexibility, maximum assembly cost, zero batteries.

  • lagodev bets on compiled, statically typed, batteries-included Go. It takes Laravel's ergonomics (Eloquent-style ORM, migrations, artisan-style CLI, queues, broadcasting, gates/policies) and reimplements them on Go's runtime: real OS threads via goroutines, a single static binary, no GC-heavy interpreter, and types that survive to runtime. The cost is youth — the ecosystem, the community, and the long tail of edge-case packages do not yet exist. See ARCHITECTURE.md for how the layers fit.

The honest one-liner: lagodev is "Laravel's feature checklist on Go's runtime." Whether that trade is worth it depends entirely on your priorities, which is what the rest of this document is for.


At-a-glance matrix

Legend: ✅ first-class / built-in · ⚠️ present but younger, thinner, or needs assembly · ❌ not provided by the core framework.

Core data layer

Capability lagodev Laravel Django NestJS Express
ORM (active-record style) ✅ generics, typed Query[T] ✅ Eloquent, mature ✅ Django ORM, mature ⚠️ via TypeORM/Prisma ❌ bring your own
Query builder ✅ chainable, single-pass SQL .filter() chains ⚠️ ORM-dependent
Migrations ✅ up/down, checksum, advisory lock ✅ autogenerated ⚠️ ORM-dependent
Relations + eager load LoadMany, no N+1 select_related ⚠️ ORM-dependent
Seeders / factories ✅ generic, topo-sorted ⚠️ fixtures + factory_boy ⚠️ assemble
Soft deletes ✅ default scope ⚠️ third-party ⚠️ ORM-dependent
Multi-DB drivers ⚠️ pg / mysql / sqlite ✅ +sqlsrv ✅ +oracle ⚠️ ORM-dependent

Web & API

Capability lagodev Laravel Django NestJS Express
Router + middleware ✅ (DRF for APIs) ✅ (this is its job)
Validation ✅ struct/request ✅ FormRequest ✅ forms / DRF serializers ✅ class-validator
API resources / serializers ✅ DRF ⚠️ interceptors
OpenAPI generation ✅ 3.1 + typed client codegen ⚠️ via packages ⚠️ drf-spectacular ✅ @nestjs/swagger
GraphQL ✅ built-in ⚠️ Lighthouse pkg ⚠️ Graphene/Strawberry ✅ first-class
Full-text search ⚠️ Scout pkg ⚠️ pg / haystack
HTTP client ⚠️ requests/httpx ⚠️ axios ⚠️
Generic collections ✅ generics ✅ Collection ⚠️

Auth, authz, realtime

Capability lagodev Laravel Django NestJS Express
Auth: session/guard ⚠️ Passport
JWT ⚠️ Sanctum/pkg ⚠️ simplejwt ⚠️ pkg
OAuth (PKCE) ✅ Passport/Socialite ⚠️ allauth ⚠️ pkg
Account / password reset ⚠️ assemble
Authz gates / policies ✅ permissions ⚠️ guards
WebSocket hub + presence ✅ native goroutines ⚠️ Reverb/Echo ⚠️ Channels ⚠️ gateways ⚠️ ws/socket.io
Broadcasting ⚠️ Channels ⚠️

Background work & ops

Capability lagodev Laravel Django NestJS Express
Queue + jobs ✅ +dashboard ✅ +Horizon ⚠️ Celery (external) ⚠️ Bull/BullMQ
Scheduling / cron ⚠️ celery-beat ⚠️ @nestjs/schedule
Events / listeners ✅ signals
Notifications ⚠️ assemble ⚠️ assemble
Mail ⚠️ pkg
Cache ⚠️ cache-manager
Filesystem (local/S3) ✅ Flysystem ✅ storages ⚠️ pkg
DI container ✅ generics, compile-checked ✅ runtime ⚠️ minimal ✅ central

Platform, ops, deploy

Capability lagodev Laravel Django NestJS Express
i18n ⚠️ pkg
Date/time helpers ✅ carbon-style ✅ Carbon ✅ datetime/arrow ⚠️ date-fns ⚠️
Crypt / hashing ⚠️ pkg
Resilience (CB/retry/timeout/RL) ✅ built-in ⚠️ pkg ⚠️ pkg ⚠️ pkg
Observability (OpenTelemetry) ⚠️ pkg ⚠️ pkg ⚠️ pkg ⚠️ pkg
Debug dashboard ✅ telescope ✅ Telescope ✅ Debug Toolbar
Admin panel ✅ generics, auto ⚠️ Nova ($) / Filament ✅ best-in-class
CLI generators lago/artisan ✅ artisan ✅ manage.py ✅ nest CLI
Single static-binary deploy ❌ runtime+ext ❌ runtime+venv ❌ node_modules ❌ node_modules
Static typing at runtime ✅ compiled Go ⚠️ hints, erased ⚠️ TS erased
True multi-core concurrency ✅ goroutines ⚠️ Octane/workers ⚠️ GIL/ASGI ⚠️ cluster ⚠️ cluster
Ecosystem & community size ⚠️ young, small huge huge ✅ large ✅ huge
Production track record ⚠️ early ✅ 15+ yrs ✅ 19+ yrs ✅ mature ✅ mature
Third-party package depth ⚠️ thin ✅ Packagist ✅ PyPI ✅ npm ✅ npm
Hiring pool ⚠️ Go devs, not "lagodev devs"

The bottom four rows are where lagodev honestly loses today, and no amount of feature breadth changes that. A framework's value is its ecosystem and the hours of production debugging others have already done for you. Laravel and Django have a fifteen-year head start; lagodev does not.


Category deep-dives

ORM

lagodev's ORM (see ORM.md, ARCHITECTURE.md) models embed orm.Model for ID/timestamps/soft-delete, and queries flow through a generic Query[T] so results hydrate into concrete structs with no interface{} casting at the call site. A reflection cache parses each struct once. Relations are plain functions; LoadMany issues a single WHERE fk IN (...) to defeat N+1 without global state.

How it stacks up:

  • vs Eloquent: Eloquent is more dynamic — magic attributes, global scopes, observers, a vast library of behaviors (spatie/* alone covers most needs). lagodev trades that dynamism for compile-time type safety: a bad column or wrong type is a build error, not a runtime surprise in production. Eloquent wins on maturity and the sheer depth of community packages; lagodev wins on the class of bugs that simply cannot occur.

  • vs Django ORM: Django's ORM and its auto-generated migrations are the gold standard for "the framework infers the schema diff for you." lagodev's migrations are explicit Up/Down with checksums and advisory locks — closer to Laravel's philosophy. Django is ahead on migration autodetection; lagodev is ahead on explicitness and on not paying interpreter cost per row.

  • vs TypeORM/Prisma (Nest): Prisma has a beautiful schema language and great DX, but it's a separate engine and codegen step. lagodev's ORM is native Go with no sidecar process. TypeORM's decorators are erased at runtime; lagodev's types are real.

Honest caveat: lagodev supports Postgres, MySQL, SQLite today. Laravel and Django reach further (SQL Server, Oracle). If you're on those, the incumbents win outright.

Auth & authz

lagodev ships guards/sessions, JWT, OAuth with PKCE, account lifecycle, password reset, and gates/policies for authorization — all in core, all typed. Laravel matches this through first-party packages (Sanctum, Passport, Socialite) that are extremely well-trodden. Django's auth + permissions are a decade-plus mature. NestJS and Express assemble it from Passport strategies and npm.

The differentiator is packaging: in lagodev these are one import away with no version-matrix to reconcile. In Nest/Express you're wiring Passport, choosing a JWT lib, and owning the integration. The incumbents' advantage is that their auth paths have survived years of pen-tests and CVE disclosures — that hardening is real and lagodev has not yet earned it. Treat auth as the area where maturity matters most.

Realtime

This is lagodev's clearest structural win. Its WebSocket hub with presence is built on goroutines and channels — Go's concurrency model is made for holding tens of thousands of long-lived connections in one process, each connection a cheap goroutine on a real thread pool.

  • Laravel offloads realtime to a separate process (Reverb, or Pusher/Soketi) because PHP-FPM cannot hold persistent connections.
  • Django uses Channels + an ASGI server + a channel layer (Redis) — it works, but it's a meaningful architectural addition fighting against the WSGI/GIL grain.
  • NestJS/Express can do WebSockets natively (ws/socket.io), but every connection competes on a single event-loop thread; CPU-bound work in one handler stalls all sockets, and scaling means clustering + a Redis adapter.

lagodev keeps realtime in-process and multi-core with no extra moving parts. For chat, presence, live dashboards, and collaborative apps, this is a genuine edge — not a marketing line.

Queues & background work

lagodev bundles queue + jobs + a dashboard and a scheduler in core — the Laravel + Horizon experience without a separate package. Laravel's queue system plus Horizon is the most mature of the bunch and the bar to beat. Django leans on Celery, a separate, heavyweight (but very capable) external system. Nest uses Bull/BullMQ on Redis. Express has nothing built in.

lagodev's advantage is integration and a single deployable that runs both web and workers. Laravel's advantage is Horizon's years of operational polish (metrics, tags, retries, failed-job UX) that lagodev's dashboard is still catching up to.

Performance & deployment

We will not quote numbers we haven't measured — see BENCHMARKS.md. Qualitatively, and uncontroversially among people who run all four runtimes:

  • Compiled Go executes as native machine code with no per-request interpreter bootstrap. PHP (without Octane) re-bootstraps per request; Python carries interpreter + GIL overhead; Node is fast but single-threaded per process and JIT-warmed.
  • Concurrency: goroutines are scheduled across all cores by the Go runtime. PHP scales by process count (FPM) or needs Octane to stay resident; Python is GIL-bound for CPU work and scales via processes/ASGI; Node scales CPU work via cluster. For mixed I/O + CPU workloads under load, Go's model is the least surprising.
  • Memory: a Go binary's footprint is typically far below a PHP-FPM pool or a loaded Python/Node process holding the same concurrency.
  • Deployment is the starkest contrast: go build produces one static binary. No runtime to install, no vendor/, no node_modules, no venv, no extension version matrix. The container is FROM scratch or distroless with one file copied in — small image, tiny attack surface, trivial rollback (it's just a binary). Laravel needs PHP + extensions + Composer deps; Django needs Python + venv + system libs; Nest/Express ship node_modules.

This deployment story alone is why some teams pick Go regardless of framework.

Type safety

lagodev's types are real at runtime because Go is compiled and uses generics throughout (Query[T], the DI container, collections, factories). A type mismatch is a go build failure on a developer's machine or in CI, before anything ships.

  • Laravel/PHP: dynamic; PHPStan/Psalm help but are opt-in static analysis bolted on, not enforced by the runtime.
  • Django/Python: type hints exist but are erasedmypy is opt-in and many libraries are partially typed.
  • NestJS/TypeScript: excellent authoring-time types, but they are erased at compile to JS; runtime validation (class-validator, zod) is a separate concern you must remember to wire.

For large teams and long-lived codebases, compiler-enforced types remove an entire category of integration bugs. This is a first-principles lagodev win.

Ecosystem & maturity (the honest part)

Here lagodev loses, and it's not close:

  • Packages: Packagist, PyPI, and npm each have hundreds of thousands of packages and a mature package for nearly every niche (payments, PDF, SSO, geo, ML glue). lagodev's third-party surface is thin; you'll write more yourself or drop to general Go libraries.
  • Community & answers: years of Stack Overflow, blog posts, and battle reports exist for Laravel/Django/Express. For lagodev, you are often the first person to hit a given edge case.
  • Hiring: you can hire "a Laravel developer" or "a Django developer" tomorrow. You hire Go developers and onboard them onto lagodev — the framework-specific pool effectively doesn't exist yet.
  • Track record: Laravel (2011) and Django (2005) have survived nearly two decades of production abuse. lagodev is early. Its breadth is impressive for its age, but breadth is not the same as the hard-won robustness that only time and thousands of production deployments produce.

Do not let the green checkmarks above obscure this. Feature parity on a matrix is not maturity parity in production.


When to choose lagodev

  • You want Go's runtime (single binary, real concurrency, low memory, static types) without assembling a framework from a dozen libraries the way you would around net/http, chi, or Express.
  • Realtime-heavy systems: chat, presence, live dashboards, collaboration — goroutines hold connections better than PHP-FPM or a single Node event loop.
  • High-concurrency, latency-sensitive APIs where interpreter overhead and GC pauses matter.
  • Ops-constrained deploys: edge, on-prem, small VPS, containers where a tiny static image and no runtime dependencies are a real advantage.
  • Teams that already know Go and like Laravel's ergonomics, and want both.
  • Greenfield services where compile-time type safety across the whole stack pays off over the project's life.

When NOT to choose lagodev

  • You need a deep ecosystem today: a specific payment SDK, SSO connector, PDF/reporting stack, or CMS that already exists for Laravel/Django but not for lagodev. Reinventing it is a real cost.
  • Risk-averse, compliance-heavy projects where you need a framework whose auth and crypto paths have years of CVE history and audits behind them. Lean on Laravel/Django/Spring-grade maturity here.
  • Your team is PHP/Python/Node and not Go — the learning curve of Go plus a young framework is a double cost; a mature framework in their language ships faster.
  • CRUD-admin-heavy internal tools where Django's admin or Laravel + Filament/Nova will out-deliver anything you'd build, faster.
  • You depend on databases beyond Postgres/MySQL/SQLite (SQL Server, Oracle) — currently outside lagodev's driver set.
  • You need the hiring liquidity of a mainstream framework right now.

Migration mental model

If you're coming from one of the incumbents, here's how concepts map. The goal is to lower the "where did my feature go?" friction.

For Laravel developers

lagodev is intentionally the closest analog — it borrows Laravel's vocabulary.

Laravel lagodev
artisan lago (alias artisan) — see CLI.md
Eloquent model struct embedding orm.Model
php artisan make:model -mfsc lago make:model -mfsc
Migrations (up/down) migrations.Define(name, up, down)
Route::resource g.Resource("posts", controller)
FormRequest validation struct/request validation
Gates / Policies gates / policies (authz package)
Horizon built-in queue dashboard
Telescope telescope debug dashboard
Broadcasting / Reverb in-process WebSocket hub
Carbon carbon package

Biggest mental shift: no facades, no magic, no per-request container reset. You pass dependencies explicitly (often via the DI container), the app is a long-lived process, and the compiler — not a runtime exception — catches your mistakes.

For Django developers

Django lagodev
manage.py lago
Models + makemigrations structs + explicit Up/Down migrations
QuerySet .filter() Query[T] chainable builder
select_related / prefetch_related LoadMany eager loading
DRF serializers API resources / serializers
django.contrib.auth auth + authz packages
Celery built-in queue + jobs
Django admin generic auto admin panel
Channels (ASGI) native WebSocket hub

Biggest mental shift: migrations are explicit, not auto-detected, and there is no global settings/app-registry singleton — wiring is explicit and typed. The trade you're making is autodetection convenience for compile-time safety and a single deployable.

For NestJS / Express developers

Nest/Express lagodev
Modules + providers + DI DI container (generics)
Decorators (@Injectable, @Get) explicit registration + struct tags
TypeORM/Prisma native ORM
class-validator / zod built-in validation
Passport strategies auth package (JWT/OAuth-PKCE/session)
Bull/BullMQ built-in queue
@nestjs/swagger OpenAPI 3.1 + typed client codegen
Gateways / socket.io WebSocket hub + presence
node_modules deploy single static binary

Biggest mental shift for Nest: types are no longer erased — what the compiler checks is what runs, so the separate runtime-validation step you wired in Nest collapses into the type system plus the validation package.

Biggest mental shift for Express: you stop assembling. The ORM, validation, auth, queues, and realtime that you'd hand-pick from npm are already in the box and designed to work together. You lose à-la-carte freedom; you gain a coherent, typed, single-binary stack.


Bottom line

lagodev offers Laravel-class breadth on Go's runtime: one static binary, real multi-core concurrency, compile-time type safety, and a built-in realtime story the PHP/Python/Node incumbents bolt on. That combination is real and, for realtime- and ops-sensitive Go teams, compelling.

What it does not yet have is the fifteen-to-nineteen years of ecosystem, community, third-party packages, security hardening, and hiring liquidity that Laravel and Django have earned. Choose lagodev when its structural advantages solve a problem you actually have — and choose a mature incumbent when ecosystem depth and battle-tested maturity are the constraint that matters most.

For measured performance, see BENCHMARKS.md. For the design that makes the above possible, see ARCHITECTURE.md.