Skip to content

Instantly share code, notes, and snippets.

@m-adityavardhan
Created September 16, 2025 17:51
Show Gist options
  • Select an option

  • Save m-adityavardhan/b53e13ff642a4248b09b7f4166d30a9d to your computer and use it in GitHub Desktop.

Select an option

Save m-adityavardhan/b53e13ff642a4248b09b7f4166d30a9d to your computer and use it in GitHub Desktop.
Evolution of web app from HTML to SSR

1) Core terms (quick)

  • SSR (Server-Side Rendering): Server returns HTML for a route. Browser may later attach JS (“hydrate”) for interactivity.
  • SPA (Single-Page App): Server returns a shell (HTML + JS bundle). JS handles routing/data on the client; page doesn’t reload.
  • MPA (Multi-Page App): Traditional pages; each URL returns fresh HTML (often SSR).
  • MVC: Architectural pattern (Model–View–Controller). Not tied to rendering mode—just organization.
  • Hydration: Client JS attaches event handlers to server-rendered HTML to make it interactive.
  • BFF (Backend for Frontend): A backend tailored to a specific UI, often aggregating multiple services.

2) Canonical stacks and what they do

  • Spring Boot + Thymeleaf (Java)

    • Rendering: SSR (MPA).
    • Pattern: MVC.
    • Data: Controllers call services/DB; Thymeleaf renders HTML.
    • Servers needed: 1 (monolith).
  • Express + Pug (Node)

    • Rendering: SSR (MPA).
    • Pattern: MVC-ish (routes/controllers + views).
    • Servers needed: 1 (monolith).
  • React/Angular/Vue SPA + API (Spring/Express/etc.)

    • Rendering: CSR (client-side) after initial bundle.
    • Data: Fetch via REST/GraphQL.
    • Servers needed: 2 (frontend asset server + backend API). You can host both in one process, but conceptually it’s two apps.
  • Next.js (React meta-framework)

    • Can do SSR, SSG (static gen), ISR (revalidate), client components, and server components (rendered on the server).
    • Has API routes (Node handlers) and in the App Router Server Actions.
    • Can talk directly to a DB (with proper pooling/auth)—so it can be a BFF or even the only backend for many apps.
    • Servers needed: flexible: 1 (monolith), or split into 2 (Next as BFF + separate microservices), depending on scale.

Misconception to fix: “Next cannot connect DB” — It can. On server routes/components you can use Prisma, Sequelize, official drivers, etc. On serverless/edge you must manage connection pooling (e.g., Prisma Data Proxy, PgBouncer, or use provider-managed pooling).

3) How many servers? (Deployment shapes)

Think logical components vs processes/servers. You can co-locate many roles in one process.

A) One server (monolith)

  • Spring Boot + Thymeleaf (HTML) + Controllers + DB
  • Express + Pug + Routes + DB
  • Next.js (Pages/App Router) + API routes/Server Actions + DB Pros: simple ops, zero CORS, shared code. Cons: scaling and team boundaries can blur as it grows.

B) Two servers

  • SPA server (React/Angular/Vite/Next static export) + API server (Spring/Express/Nest).
  • Next.js (BFF: UI + some APIs) + Core backend (Java/Node/Go) for heavy business logic. Pros: clearer separation, scale independently. Cons: CORS, more infra, API contracts to manage.

C) Three+ servers (service/microservice mesh)

  • Next.js front/BFF + multiple domain services (auth, orders, inventory…). Pros: autonomy, scale per domain, resilience. Cons: ops overhead, distributed complexity, observability needed.

4) Where your statements need tweaks

  • “SSR = MVC only 1 server” → SSR can be MVC or not; and it can run on 1 or many servers. SSR is about where HTML is rendered, not team topology.
  • “SSR + SPA needs 3 servers (Next + backend)” → Not necessarily. Next.js alone can do SSR + SPA-like interactivity + APIs in 1 server. You might add a separate backend (making 2) for scale or domain separation. You only get to 3+ when you split into multiple backend services.

5) Practical decision guide

Small/medium product or prototype

  • Use Next.js monolith: UI (Server & Client Components) + API routes/Server Actions + DB.
  • Benefits: great DX, SSR for SEO, SPA feel post-hydrate, fewer moving parts.

Growing app with heavier domain logic

  • 2 servers: Next.js (BFF + SSR) + a backend (Spring Boot/NestJS) for complex workflows, scheduled jobs, and integrations.
  • Keep auth/session and request shaping in BFF; domain services stay clean.

Large org, many domains

  • Next.js front/BFF + multiple microservices (Java/Node/Go) + async messaging (Kafka/SQS), API gateway, observability stack.

6) Concrete mappings

  • “true SSR” examples

    • Spring/Thymeleaf: Controller → Service/Repo → Thymeleaf template → HTML.
    • Express/Pug: Route → Service → Pug template → HTML.
    • Next.js: Route (server component) → fetch DB → return JSX → HTML, then hydrate.
  • Data fetching

    • MVC: Controller queries DB and renders view.
    • SPA: Browser calls API; API queries DB.
    • Next.js: Server components/actions or API routes query DB; client calls these endpoints where needed.

7) Answers to your final questions

“SSR + SPA—can’t we do it in 2?” Yes. Next.js gives you SSR + SPA feel in one app. Add a single backend service (if needed) and you’re at 2. Many teams run just Next.js (1 server) successfully for a long time.

“Can Express do what Next does?” Express can render templates (SSR) and serve APIs, but it doesn’t provide the React rendering pipeline (server components, routing conventions, SSG/ISR, automatic code-splitting, image/font optimizations, built-in bundling). You’d have to assemble those yourself.

“Is Next a BFF?” It can be. When you put API routes/Server Actions in Next and call downstream services/DB, it’s effectively a BFF.

8) Quick “when to choose what”

  • SEO + fast first paint + minimal ops: Next.js monolith.
  • Strong React SPA + strict backend separation: SPA (Vite/CRA) + separate backend.
  • Java-heavy org & server-rendered HTML: Spring Boot + Thymeleaf (or Express + Pug in Node world).
  • Long-term React with SEO and flexibility: Next.js front + domain backend(s).

9) Clarifying few things

1. MVC vs. “MVC-ish”

MVC = Model–View–Controller.

  • Model = data & business logic (DB, queries, domain rules).
  • View = templates or components that generate UI (HTML, JSON, etc.).
  • Controller = glue: takes input (HTTP request), asks the Model for data, passes it to the View, and returns a response.

👉 In Spring Boot + Thymeleaf, MVC is formal:

  • Model = JPA entities / service layer
  • Controller = annotated @Controller classes
  • View = Thymeleaf templates that render HTML

👉 In Express + Pug, MVC is more “loose” (hence MVC-ish):

  • Controller = route handlers (app.get('/todos', ...))
  • View = Pug templates
  • Model = sometimes you code it cleanly (separate DB layer), sometimes you just query the DB inline. So it’s not a strict pattern unless you enforce it → that’s why I said “MVC-ish.”

2. SSR can be MVC or not

SSR (Server-Side Rendering) just means HTML is generated on the server and sent to the client.

  • SSR with MVC:

    • Spring Boot Controller queries DB (Model) → Thymeleaf (View) generates HTML → browser displays it.
    • Classic “MVC” web app.
  • SSR without MVC:

    • Next.js Server Component fetches data directly and returns HTML.
    • There’s no explicit “controller class” or “model layer” — just React code that happens to run on the server and output HTML.
    • Still SSR, but not necessarily MVC.

So: SSR = rendering strategy; MVC = architectural pattern. They can overlap, but one does not imply the other.


3. SSR ≠ 1 server only

Some people think “SSR = monolith.” Not true.

  • You can do SSR in a monolith: one server handles HTML + DB + business logic (e.g., Spring Boot + Thymeleaf).

  • Or in a multi-tier system:

    • Next.js server renders HTML (SSR)
    • Calls APIs from a backend service (Java/Spring, Node, etc.)
    • Backend service fetches DB
    • Next returns HTML to browser

👉 Both are SSR, regardless of server count. That’s why I wrote: SSR is about where HTML is rendered, not team topology (1 vs. many servers).


Summary in one line:

  • MVC = how you structure your code (Model/Controller/View).

  • SSR = where HTML is generated (server vs. client).

  • You can have:

    • SSR + MVC (Spring Boot + Thymeleaf)
    • SSR without MVC (Next.js server components)
    • MVC without SSR (React SPA with MVC-ish backend APIs).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment