⌨️ Web development

Static hosting and CDNs: what a developer needs to know

Atomic deploys, previews, redirects and rewrites, 404 pages, environment variables and edge functions: how to work well with static hosting and CDNs.

Static hosting platforms have changed the way sites are published: you connect a repository, specify the build command and the output folder, and on every commit the site is rebuilt and distributed across a network of servers around the world. Behind this simplicity, however, there are a few concepts worth knowing, because they determine how URLs behave, how secure your secrets are and how quickly updates arrive.

What a CDN really does

A CDN (Content Delivery Network) is a set of servers distributed across many locations. When a user requests a page, the nearest node, which holds a copy of the files, responds. For a static site, the CDN is often the host itself: files are uploaded directly to the delivery network at publish time.

The advantage is not just speed. A CDN absorbs traffic spikes, terminates HTTPS connections close to the user and can apply rules (headers, redirects, compression) without you having to manage a server.

The publishing workflow

Reproducible builds

The platform runs the build in a clean environment on every deploy. That means everything required must be declared in the project: language or Node version, dependencies locked in a lock file, an explicit build command. If the site "works on my machine" but not on the platform, one of these pieces of information is almost always missing.

Atomic deploys

Most platforms publish atomically: the new version is uploaded in full and only at the end is traffic switched from the old version to the new one, in one go. There is no moment when the site is half old and half new. Previous versions also remain available, and rolling back takes a click.

Previews

For every branch or change request the platform can create a separate preview address. It is the ideal tool for having a change checked before publishing it. Remember, though, that previews are public to anyone who knows the address: they should not contain confidential data and should not be indexed. Many platforms automatically add an X-Robots-Tag: noindex header on preview addresses, but check it.

Redirects and rewrites

Routing rules are written in a platform configuration file. The syntax varies, but the concepts are common:

  • Redirect: the browser receives a 301 or 302 code and changes address. It is used for moved or renamed URLs.
  • Rewrite: the server serves a different file while keeping the requested URL. It is used, for example, by single-page applications, where every route must return index.html.

An example in configuration-file style:

/old-article    /new-article        301
/blog/*         /articles/:splat    301
/app/*          /app/index.html     200

The last line is a rewrite (code 200). Watch out: a catch-all rewrite to index.html means non-existent URLs also respond with 200. If the site is not a single-page application, prefer returning a real 404 page.

The 404 page

Almost every platform automatically serves a 404.html file from the site root, with the correct status code. Create one: it is the page users see when they follow broken links, and it is worth offering a search box or the main links.

Custom headers

Security and caching headers are configured in the same file or in a dedicated one, mapped to paths:

/*
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

/assets/*
  Cache-Control: public, max-age=31536000, immutable

After every change, check the actual responses: a syntax error in the configuration file is often ignored without warning.

Environment variables and secrets

This is where the most dangerous mistake hides. Platforms let you define environment variables for the build, and many frameworks expose variables with a certain prefix to browser code. Everything that ends up in the JavaScript sent to the browser is public: anyone can read it in the developer tools.

  • Keys intended for the browser (public service keys, analytics identifiers) can sit in the bundle, as long as they are restricted on the service side, for example to your domains.
  • Secret keys (database access, paid APIs, admin tokens) must never end up in the bundle. They should only be used in server-side functions.
  • Do not store secrets in the repository, not even in private branches: Git history keeps them.

Serverless and edge functions

When a static site needs a bit of logic (submitting a form, calling an API with a secret key, verifying a token), platforms offer small functions that run on demand. Serverless functions usually run in one region; edge functions run on the CDN nodes, close to the user, with tighter limits on duration and resources.

Treat them like any server-side code: validate input, handle errors, rate-limit requests and never return internal details in error messages.

Invalidating the CDN cache

With atomic deploys, the platform usually invalidates the cache of changed files automatically. If instead you use a separate CDN in front of an origin, you may need to trigger a purge manually after publishing. The most robust strategy remains hashed file names for assets and a short or validated cache for HTML: that way invalidation becomes almost unnecessary.

In short

  • A CDN serves files from the node nearest the user and absorbs traffic spikes.
  • Make the build reproducible and use atomic deploys and previews, which should not be indexed.
  • Distinguish redirects from rewrites and serve a real 404 page with the correct code.
  • Everything in browser JavaScript is public: secrets belong only in server-side functions.
  • Treat serverless and edge functions as fully fledged backend code.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. A computer science graduate, he combines rigorous technical analysis with attention to the people who use technology.

Read also