This video undertakes a comprehensive comparative analysis of five distinct web development technology stacks, spanning a decade of evolution: Ruby on Rails, Elixir with Phoenix LiveView, Go with GraphQL and a React Single Page Application (SPA), the T3 Stack (Next.js Pages Router, tRPC, Prisma), and Next.js App Router with React Server Components (RSC). The creator systematically rebuilds the same "Roundest" application across each stack, meticulously evaluating them based on setup complexity, developer experience (DX), performance, code maintainability, and deployment strategies (primarily using Fly.io and Vercel). The analysis reveals the strengths and weaknesses inherent in different architectural approaches, from traditional MVC to modern full-stack TypeScript and server-driven UI, ultimately highlighting React Server Components as a paradigm shift offering exceptional simplicity, composability, and unparalleled performance.
Evaluating Web Development Stacks: A Decade of Building "Roundest"
0:00 Introduction & Project Goal: The creator aims to build the same web application, "Roundest," five times using different technology stacks he's encountered over the past decade, evaluating their setup, developer experience, performance, and deployment. Fly.io and Vercel are acknowledged as key hosting sponsors.
Setup Challenges: Mac setup instructions were outdated, PostgreSQL setup was difficult (often defaulting to SQLite for development), and relevant Stack Overflow answers were frequently 10+ years old. Initial setup could take over 6 minutes due to gem installations, and installing Tailwind CSS was particularly problematic, requiring a specific, undocumented data-turbo-track-reload attribute.
Developer Experience (DX): The Model-View-Controller (MVC) structure resulted in a high file count (83 files for ~1000 lines of code), necessitating frequent jumps between many small files. While the Active Record ORM was praised for its robust migration system, the "magic" behind naming conventions for migrations was seen as unintuitive and tedious.
Performance: Surprisingly fast, especially when deployed close to the user, but each vote required two network requests (a POST followed by a GET redirect) which is inefficient.
Deployment (Fly.io): Exceptionally smooth, with fly launch intelligently detecting Rails, configuring PostgreSQL, and handling environment variables. Fly.io's feature of "sleeping" inactive services to reduce costs for side projects, waking them up quickly on demand (after a cold start), was highly valued.
Key Takeaway: Rails pioneered many influential patterns and remains stable, but its setup and file-hopping DX can feel dated, despite Fly.io offering a seamless deployment experience.
Performance Breakthrough: Achieved "pretty dang fast" performance due to LiveView's websocket connection, sending minimal diffs to update the UI. A "Turbo version" that preloaded images resulted in "stupidly fast" interactions, possibly the fastest overall.
DX & Language Features: Praised Elixir's functional programming paradigm, especially "pipes" for elegant function chaining and "pattern matching" for concise function definitions. The LiveView mental model, where assigning new values to the socket automatically re-renders the UI, eliminated complex client-side state synchronization. Asynchronous tasks (Task.start) allowed for non-blocking operations.
Setup & Quirks: Fewer files (47 total, 31 Elixir) than Rails but slightly more lines of code. Seeding the database in production was cumbersome, requiring custom modules and SSH access. A "double mount" bug (server-side render then websocket connect) required an initial "loading" state to prevent UI flicker.
Deployment (Fly.io): Very easy (fly deploy) and fast for updates after the initial build.
Key Takeaway: Elixir with Phoenix LiveView delivers incredible performance and a delightful, productive functional programming developer experience, though some setup and deployment quirks were noted.
Frontend DX (React + Apollo): GraphQL Explorer was a significant positive, simplifying query construction. Apollo Client's useQuery and useMutation hooks facilitated non-blocking client-side updates.
Backend DX (Go): Go's struct tags for database and JSON mapping were appreciated. GraphQL Studio provided a useful playground for testing backend queries and mutations.
"Type Generation Hell": Generating TypeScript types from GraphQL schema proved to be an extremely frustrating and time-consuming process (hours spent), requiring specific syntax and configurations to work with Apollo and Prettier.
Nullability: GraphQL's default nullability for all fields led to excessive assertions and exclamation points in the code, hindering type safety efforts.
Backend/Frontend Wall: The strong separation between frontend and backend, while enabling independent development, often resulted in less optimized APIs (e.g., generic Pokemon lists instead of specific random pairs), demonstrating a common challenge in large teams.
Deployment (Fly.io): "Painless" (fly launch) for the Go backend.
Code Complexity: Combined frontend and backend code resulted in 952 total lines (14 TypeScript, 5 Go files), reflecting the cost of separation.
Key Takeaway: GraphQL offers powerful API standardization and excellent developer tooling (especially the dev tools), making it suitable for large organizations. However, the friction points around type generation and nullability can severely degrade the developer experience.
56:02 T3 Stack (Next.js Pages Router, tRPC, Prisma):
Developer Experience: Praised for its excellent integration, allowing command-click navigation directly from frontend calls (tRPC) to backend code within the same TypeScript codebase, eliminating GraphQL's nullability and type generation issues. Prisma ORM's schema definition was also highlighted as a clear source of truth.
Performance: "Fine," but suffered from cold starts, with nothing happening on the client until the server and database spun up, leading to noticeable delays for initial interactions.
Layouts (Pages Router): The biggest negative. Implementing shared layouts was described as "hellish," requiring complex boilerplate in _app.tsx and custom getLayout functions, without support for nested layouts. This was deemed a significant drawback that could deter new users.
Seeding: Lacked official guidance, requiring a custom seed.ts script executed with tsx (TS node was unreliable). No built-in production seeding.
Code Complexity: Achieved the smallest full-stack codebase among the first four stacks, with 600 total lines (13 TypeScript files), demonstrating that combining backend and frontend can simplify logic.
Deployment (Vercel): Smooth, via vercel deploy or GitHub integration.
Key Takeaway: T3 Stack offers an outstanding integrated DX with strong type safety and reduced code complexity. However, the pages router's layout system is a significant pain point, and cold start performance remains a challenge.
1:08:25 Next.js App Router (React Server Components - RSC):
Performance & Efficiency: "Phenomenal" performance, potentially "slightly faster than the Elixir version." Achieved a "single-flight mutation," where a single POST request sends data and receives the updated page, eliminating multiple round trips or websockets.
Simplicity & Composability: Described as the "simplest version," with main page logic being concise. Server Functions ('use server') allow client-callable server-side code directly within components.
Native Caching: Leverages powerful caching primitives, with getAllPokemon (from an external API) being heavily cached, eliminating the need for a separate database or seeding for Pokemon data. kv (Vercel's Upstash wrapper) was used for vote storage.
Over-optimization (Turbo Version): An advanced optimization stores the current Pokemon in a cookie and prefetches the "next pair" in a hidden div. Updating the cookie in a server action triggers a page re-render (without invalidating all caches), providing superior performance compared to revalidatePath for heavily cached applications.
Layouts: Effortless "actual stacking layouts with the routing" compared to the Pages Router.
Code Complexity: The smallest codebase overall, with 367 total lines across 12 files (after cleanup), underscoring its efficiency.
Key Takeaway: React Server Components offer an "unreal" blend of simplicity, composability, and unmatched performance. It represents a significant leap in developer experience, making complex caching and server-side interactions straightforward and efficient.