---
title: "26 — Deployment — When a Push Became a Release"
uid: deployment
tags: ["deployment", "vercel", "netlify", "ci-cd", "cloudflare", "github-pages", "roadmap:frontend"]
excerpt: "Modern platforms wire git → build → global CDN automatically — deploy became a push, not a ceremony. Picking a platform is picking a band on that pipeline."
date: 2026-08-12T18:35:07+0000
source: https://www.aveshina.my.id/en/blog/deployment
---

"Upload files to a server" was my deployment model, and it described a ritual that no longer exists. The one sentence that replaced it: **modern platforms wire git → build → global CDN (content delivery network — servers spread worldwide) automatically, so deploy became a push, not a ceremony.** [1] The thing that used to be a multi-step ritual — FTP the files (an old protocol for copying files to a server), restart the server, pray — is now an event triggered by git push. Every platform I'll walk through is just a different opinion about how much of that pipeline it owns for me.

Here's the pipeline I keep in my head. Three stages, owned by different layers, that every deploy passes through in order. The platforms differ only in *which* stages they automate and *how far out* they push the result:

```figure
<svg viewBox="0 0 740 300" xmlns="http://www.w3.org/2000/svg" class="my-6 w-full max-w-2xl" role="img" aria-label="The deploy pipeline. A git push icon on the left feeds a BUILD stage that compiles the app, which feeds a CDN stage that distributes the result to edge nodes near users. Four labels underneath show where platforms sit: GitHub Pages owns only static files; Vercel and Netlify own build plus edge or serverless; Cloudflare adds its global network plus Workers; Railway and Render own build plus a long-running server.">
  <defs>
    <marker id="darrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
      <path d="M0,0 L10,5 L0,10 z" fill="#64748b"/>
    </marker>
  </defs>
  <g font-family="ui-sans-serif, system-ui, sans-serif" text-rendering="geometricPrecision">

    <!-- git push -->
    <rect x="20" y="70" width="130" height="80" rx="10" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.5"/>
    <text x="85" y="98" font-size="13" font-weight="700" fill="#1e1b4b" text-anchor="middle">git push</text>
    <text x="85" y="118" font-size="10" fill="#475569" text-anchor="middle">the trigger</text>
    <text x="85" y="134" font-size="10" fill="#475569" text-anchor="middle">origin/main</text>

    <!-- build -->
    <rect x="200" y="70" width="150" height="80" rx="10" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.5"/>
    <text x="275" y="98" font-size="13" font-weight="700" fill="#422006" text-anchor="middle">BUILD</text>
    <text x="275" y="118" font-size="10" fill="#475569" text-anchor="middle">install, compile,</text>
    <text x="275" y="134" font-size="10" fill="#475569" text-anchor="middle">bundle static output</text>

    <!-- CDN / edge -->
    <rect x="400" y="70" width="160" height="80" rx="10" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
    <text x="480" y="98" font-size="13" font-weight="700" fill="#052e16" text-anchor="middle">GLOBAL CDN</text>
    <text x="480" y="118" font-size="10" fill="#475569" text-anchor="middle">edge nodes near users</text>
    <text x="480" y="134" font-size="10" fill="#475569" text-anchor="middle">live URL</text>

    <!-- arrows -->
    <line x1="150" y1="110" x2="198" y2="110" stroke="#64748b" stroke-width="1.5" marker-end="url(#darrow)"/>
    <line x1="350" y1="110" x2="398" y2="110" stroke="#64748b" stroke-width="1.5" marker-end="url(#darrow)"/>

    <!-- live URL bubble -->
    <rect x="600" y="78" width="120" height="64" rx="8" fill="#fce7f3" stroke="#db2777" stroke-width="1.5"/>
    <text x="660" y="103" font-size="12" font-weight="700" fill="#500724" text-anchor="middle">live URL</text>
    <text x="660" y="122" font-size="10" fill="#475569" text-anchor="middle">users hit the edge</text>
    <line x1="560" y1="110" x2="598" y2="110" stroke="#64748b" stroke-width="1.5" marker-end="url(#darrow)"/>

    <!-- where platforms sit -->
    <g font-size="10" fill="#475569">
      <rect x="200" y="180" width="150" height="20" rx="4" fill="#fffbeb" stroke="#ca8a04" stroke-width="0.8"/>
      <text x="275" y="194" text-anchor="middle">GitHub Pages · static only</text>

      <rect x="170" y="206" width="240" height="20" rx="4" fill="#fef9c3" stroke="#ca8a04" stroke-width="0.8"/>
      <text x="290" y="220" text-anchor="middle">Vercel · Netlify — build + edge/serverless</text>

      <rect x="170" y="232" width="390" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="0.8"/>
      <text x="365" y="246" text-anchor="middle">Cloudflare — its own global network + Workers on top</text>

      <rect x="200" y="258" width="330" height="20" rx="4" fill="#e0e7ff" stroke="#6366f1" stroke-width="0.8"/>
      <text x="365" y="272" text-anchor="middle">Railway · Render — build + long-running server</text>
    </g>
  </g>
</svg>
```

Two ideas from the pipeline underpin everything: the deploy is **event-driven** (a push is the event), and the result is **edge-distributed** (copies of the output sit near users, not in one city). The platforms are opinions about those two ideas. The rest of these notes is just grouping them by capability.

## GitHub Pages — static, free, last to touch nothing

GitHub Pages is the simplest possible opinion: it serves static files straight out of a repository [2]. No build step it owns (Jekyll aside), no server runtime, no functions. Push HTML/CSS/JS to a branch, get a URL at username.github.io. It's free, it supports custom domains and HTTPS, and it is the right answer for docs, portfolios, and anything genuinely static.

The catch is in the name — *static*. The moment the app needs a server (a database, server-side rendering on every request, an API route), Pages stops being enough. I think of it as the floor of the pipeline: the build stage produces .html files, and Pages just stands them up. For the things it fits, it's hard to beat the price.

## Vercel and Netlify — frontend/framework-native, build wired in

Vercel and Netlify are where the pipeline gets fully automated for frontend and full-stack-framework work [3][4]. Connect a Git repo once, and from then on every push to main triggers a build, the build output ships to a global CDN, and I get a live URL — preview URLs per pull request included. This site, aveshina.my.id, runs exactly this way on Vercel: a push to the repo builds the Next.js app and redeploys automatically, no ceremony [3].

What makes them "framework-native" is that they understand the build. They detect Next.js, Nuxt, Astro, Remix and run the right build command, then route the output correctly — static assets to the CDN, server-rendered routes and API handlers to **serverless functions** (short-lived code that runs on demand, with no server you manage) or **edge functions** (the same, running at the edge near users) at the same edge nodes. So the same push that ships a static page also ships a function that runs close to the user. The mental shift from Pages: the platform doesn't just *host* my output, it *ran* my build and knows what's static versus dynamic, and places each piece accordingly.

Vercel and Netlify are close enough in shape that choosing between them is usually about framework fit and how pleasant the workflow feels — Vercel is built by the Next.js team, so the integration is tightest there — rather than a difference in *what* the pipeline does. Both own build + edge/serverless.

## Cloudflare — the edge network, plus Workers

Cloudflare is a different shape, because Cloudflare *is* the network for an enormous fraction of the internet [5]. The model starts one layer below hosting: Cloudflare sits as a reverse proxy (a server that stands in front of your server, intercepting requests) in front of a site, caching content at edge locations worldwide, providing TLS (the encryption behind HTTPS), and absorbing DDoS (distributed denial-of-service — a flood of traffic meant to take the site down) traffic before it ever reaches an origin (your actual server). That same edge network powers Cloudflare Pages (static/frontend hosting with git-triggered builds) and Cloudflare Workers — functions that run *on* the edge, in the same request, without a round trip to an origin server.

The distinction worth holding onto: Vercel/Netlify *use* a CDN to deliver their build output, but Cloudflare *operates* the CDN and lets me run code directly on it. Workers aren't "serverless functions that cold-start somewhere (spin up from scratch on each call)" — they're scripts executed at the edge, milliseconds from the user, on a network Cloudflare controls end to end [5]. For a site that's globally read-heavy, or where I want compute pushed as close to the user as the cache is, that's the lever. Cloudflare is the pipeline with the network itself pulled into the platform.

## Railway and Render — full-stack app platforms

Railway and Render step off the static/frontend axis entirely [6][7]. They're general-purpose app platforms: push a repo, they provision (spin up) a container (an isolated package of your app and its dependencies), run the build, and keep a **long-running process** alive — a Node server, a Python API, a Postgres database, a worker. They automate the infrastructure (server provisioning, networking, scaling, TLS) that on a raw VPS I'd be doing by hand, but the unit they host is a *process*, not a static bundle.

This is the band to reach for when the app genuinely needs a server that's always on and stateful — a long-lived WebSocket gateway (a two-way connection that stays open), a backend with a database it talks to directly, a cron worker (a scheduled background job) — and I'd rather not operate that server myself. They still do git-triggered continuous deployment and they still sit behind infrastructure that's geographically distributed, but the model is "run my service," not "ship my build output to an edge." Deploy on Railway or Render means a new version of a running service, replacing the old one with health checks in between — closer to classic release engineering than to a static site flip.

## How the build reaches the CDN

One detail I had to straighten out: what the build stage actually produces, and why a "global CDN" matters at all. The build turns my source into **output** — for a static site, a folder of HTML/CSS/JS; for a framework like Next.js, a mix of static files, server-rendered routes, and serverless handlers. The platform uploads that output, then the CDN replicates it to edge locations. When a user types the URL, DNS (the layer from the internet-anatomy notes) resolves to a nearby edge node, and the request is served from there instead of from one origin city [8].

That's the whole reason a user in Jakarta and a user in London both see a fast site from the same deploy: neither is hitting my box — they're each hitting a copy of the output close to them. The "deploy" isn't really "put files on a server." It's "rebuild the output and invalidate the old copies at the edge." Once that's automated off a git push, the ceremony is gone, and release becomes a thing that just happens to main.

## How I use this

The habit these notes left me with is a single sorting question before I deploy: *what does this app need at runtime?* If the answer is "nothing — just serve files," GitHub Pages. If it's "a modern framework with some server routes," Vercel or Netlify (this portfolio lands here). If I want compute running *on* the edge network itself, Cloudflare. If it's "a long-running server with a database," Railway or Render. Picking a platform is really picking the band on the git → build → CDN pipeline that matches what the app actually does at runtime — and once that match is right, the deploy takes care of itself.

## References

[1] Vercel, "Deployments," Vercel Docs, 2024. [Online]. Available: [https://vercel.com/docs/deployments](https://vercel.com/docs/deployments)

[2] GitHub, "About GitHub Pages," GitHub Docs, 2024. [Online]. Available: [https://docs.github.com/en/pages](https://docs.github.com/en/pages)

[3] Vercel, "Vercel Documentation," 2024. [Online]. Available: [https://vercel.com/docs](https://vercel.com/docs)

[4] Netlify, "Get started with Netlify," Netlify Docs, 2024. [Online]. Available: [https://docs.netlify.com/](https://docs.netlify.com/)

[5] Cloudflare, "What is Cloudflare?," 2024. [Online]. Available: [https://www.cloudflare.com/en-gb/learning/what-is-cloudflare/](https://www.cloudflare.com/en-gb/learning/what-is-cloudflare/)

[6] Railway, "Quick Start Tutorial," Railway Docs, 2024. [Online]. Available: [https://docs.railway.com/quick-start](https://docs.railway.com/quick-start)

[7] Render, "Render Documentation," 2024. [Online]. Available: [https://render.com/docs](https://render.com/docs)

[8] Cloudflare, "What is a CDN?," 2024. [Online]. Available: [https://www.cloudflare.com/en-gb/learning/cdn/what-is-a-cdn/](https://www.cloudflare.com/en-gb/learning/cdn/what-is-a-cdn/)

```quiz
Q: On a modern platform, what actually triggers a deploy?
- Manually uploading files via FTP
- A git push to the connected branch
correct: 1
explain: Modern platforms wire the pipeline to Git — a push to main is the event that kicks off build, then CDN distribution. Deploy became a push, not a ceremony.

Q: You have a pure static portfolio (HTML/CSS/JS, no server). The cheapest correct home for it is…
- GitHub Pages
- Railway
correct: 0
explain: GitHub Pages serves static files straight from a repo for free. Railway is a full-stack app platform meant for long-running services — overkill for purely static output.

Q: What makes Vercel and Netlify "framework-native" rather than just static hosts?
- They run your build and place static output on the CDN and server/API routes on serverless or edge functions
- They are the only platforms that support custom domains and HTTPS
correct: 0
explain: They detect the framework, run the right build, and route the result — static assets to the CDN, dynamic routes and handlers to serverless/edge functions at the same edge. Custom domains and HTTPS are table stakes everywhere.

Q: What's the real difference between Cloudflare and Vercel/Netlify's CDN?
- Nothing — they all just host static files the same way
- Cloudflare operates the edge network itself and lets you run code (Workers) directly on it
correct: 1
explain: Vercel/Netlify use a CDN to deliver their build output. Cloudflare *is* the network and lets you run Workers on the edge, in the same request, without a round trip to an origin.

Q: Your app needs a long-running Node server with its own Postgres database. The best-fit band is…
- GitHub Pages
- Railway or Render
correct: 1
explain: Railway and Render host long-running processes and databases — exactly what a stateful backend needs. Pages can't run a server at all.
```
