Sometimes improving availability does not require another infrastructure layer. It requires asking why the page depended on so many layers in the first place.
TL;DR
During a recent migration, I revisited static sites that had been published in the same cluster—a coordinated group of servers—already used for more complex services. No one had built a cluster to serve an institutional page: we had reused infrastructure that already existed. The cost of that convenience became visible when an outage triggered by one server affected the group and took down simple pages that could have been distributed through static hosting, such as the Cloudflare Pages Free plan. In one case, server-side rendering (SSR)—where the server prepares a page’s HTML during the visit—was inherited from the default architecture of Codex’s site-creation feature in the installed version 0.1.46 and the three runs I observed, even though the interface did not need to generate new content on every visit. Clusters and SSR are useful capabilities, not automatic certificates of maturity. If the result can be produced before the request and distributed as HTML for content structure, CSS for presentation, and JavaScript for behavior, removing the application server from the critical path—the set of components that must work to answer each visit can reduce failure points, operational work, and coupling—the strength of the dependencies between components. This does not make every application a candidate for static hosting, nor does it eliminate external dependencies. The mature decision is to determine what truly needs to happen during each request and keep only what provides value at that moment in the path.
Context matters. The cluster had not been created to host a landing page. It already existed, supported services with more complex operational needs, and provided a familiar path for deployment, routing, and monitoring. Reusing it for the site was a pragmatic decision at the time—not an exercise in building infrastructure for sport.
The outage made the coupling visible. A problem that started on one server did not affect only the workloads that truly needed the cluster: it also took down a presentation interface that could have remained available independently.
During that migration, I therefore had to answer a simple question about an architecture that had grown through convenience:
If this site delivers files that were already finished before anyone visited, why does it need to survive my cluster?
The site did not process a purchase. It did not assemble a different page for each visitor. It did not query a database to decide which headline to display. It did not carry a secret business rule that had to remain on the server.
It was, essentially, a presentation interface.
Even so, staying online required a healthy private network, a set of machines coordinated as one unit—the cluster—running services, routing, correctly published versions, and a fair number of operational pieces agreeing not to have a bad day at the same time.
At the outset, it was pragmatic.
In practice, a simple page had inherited the failure domain of the entire infrastructure: if any important link in that chain stopped, the visitor would no longer receive a file that could already have been ready.
I had not bought a bazooka to kill a fly. The bazooka was already there, working, and reusing it seemed practical.
The problem was making the fly depend on the bazooka’s maintenance schedule.
A static site is not a site without engineering
To some people, the word “static” still sounds like a synonym for old, limited, or amateur.
It is not.
A static site is one whose deliverable content can be built before a visit. The browser requests a file and receives that file without depending on an application server to produce the page again at that moment. MDN explains this distinction between serving files as they are and running software to assemble dynamic content before responding.
This does not mean the project was handwritten in a 1998 index.html.
It can contain React components—reusable pieces of an interface—style processing, image optimization, internationalization—preparing a product for different languages and local conventions—tests, link validation, and a complete construction step—the build. The difference is when that work happens.
Instead of repeating part of it whenever someone opens the page, the system produces a set of HTML, CSS, JavaScript, fonts, and images in advance. Vite documents that its production build produces, by default, a bundle suitable for a static hosting service.
There is engineering before publication.
There is simply no obligation to keep an application server running to deliver the result afterward.
SSR is a capability, not a medal
On that site, the origin of SSR was less epic and more ordinary: some time earlier, I had decided to test Codex’s site-creation feature. I was lazy. Instead of questioning every architectural decision, I accepted the structure it delivered—and it came with server-side rendering (SSR).
I later opened version 0.1.46 of the OpenAI Sites package installed in my environment—the local set of rules guiding this type of generation—and the explanation became more precise. It does not literally say “use SSR on every site.” In that version, however, it instructs new sites to start from the OpenAI Sites scaffold—an initial code structure—produce output compatible with Cloudflare Workers, and provide hosting with a server artifact as well: a package prepared to run server-side code. OpenAI’s own integration manages the actual Cloudflare resources and deployment wiring. This inspection is identified local evidence, not a public specification or a claim about every past or future version of the feature.
This was not an isolated coincidence either. I ran three sites through the same skill—a reusable package of instructions, resources, and procedures that guides the agent—and all three received this strategy. In this case, it was part of the OpenAI Sites package mentioned above. The observed repetition matches the written rule: the solution starts prepared for a case in which something may need to run on the server. For a general-purpose site builder, that is an understandable precaution. For a simple page, it means inheriting an execution infrastructure it may never actually use.
In this model, application components become HTML in a server environment. React’s own documentation describes its server APIs as resources used at the top level of an application to generate the initial HTML.
It is the digital equivalent of using the knife in front of us to tighten a screw. Depending on the knife and the screw, it may even turn. The problem appears solved, but that does not turn the knife into a screwdriver or make it the most appropriate method.
The generator offered a solution capable of doing more and successfully published the site. I was the one who failed to stop and ask whether that “more” was part of the requirement. The available tool may solve the problem; the responsibility for checking whether it is also appropriate remains mine.
SSR can be the correct choice.
It can help when content genuinely varies with each request, when the response depends on a session, when personalization must not be sent to the browser, when there are specific time-to-content requirements, or when the architecture needs to combine dynamic data and initial HTML.
But in this case, a function ran to deliver an interface that could have been built beforehand.
The server woke up, prepared the tray, and delivered a dish that was already ready.
We call that modern architecture because “someone turned on a function to return files” does not look quite as good in a presentation.
The problem is not SSR.
The problem is treating it as mandatory evolution. A capability stops demonstrating maturity when it is present without a corresponding requirement. At that point, it merely demonstrates that we can operate one more thing.
And everything we can operate is also something we can break, update, monitor, pay for, and try to understand at two in the morning.
The reading path was carrying dependencies that belonged to publication
This distinction changed how I looked at the system.
Some dependencies are needed to produce a new version of the site: the repository, build tools, tests, validation, the service receiving the artifact—the generated set of files—and the approval process.
Other dependencies are needed to read the version already published.
Those two lists do not have to be identical.
If the build process becomes unavailable, I may be unable to publish a new version at that moment. That is a real problem. It should not automatically prevent someone from reading the files from the version that had already been published.
When I put the site in the same operational path as dynamic services, databases, internal networks, and other applications, I couple reading to problems unrelated to it.
An auxiliary service fails, and the institutional page falls with it.
Cluster maintenance takes the documentation offline.
A problem in the mechanism used to package and publish services prevents the recovery of an interface that, after the build, was merely a set of files.
I did not necessarily gain resilience by having more components.
I gained more components capable of participating in the outage.
Resilience can also come from subtraction
Engineering has an understandable tendency to respond to risk by adding things.
Another replica—an additional copy of the application ready to serve. Another server. Another load balancer—the component that distributes requests across available copies. Another monitoring system—the one that tracks signals and alerts when something leaves the expected range. Another recovery mechanism. Another dashboard to observe the dashboard that observes the service.
Sometimes, that is exactly what the system needs.
At other times, the more valuable question is:
Which of these pieces no longer needs to participate in this delivery?
The simplicity chapter in Google’s Site Reliability Engineering book distinguishes the problem’s essential complexity from complexity introduced by how we chose to solve it. It also highlights the value of removing code and responsibilities that no longer serve the system’s purpose.
That source does not prove that every static site will be more available on a managed platform. It supports a narrower principle: operational simplicity and loose coupling help make systems easier to understand, test, and operate reliably.
My synthesis from this case is direct: if a dependency does not need to participate in reading, removing it from the critical path can be a resilience measure.
It is not “less engineering.”
It is engineering applied to stop operating what did not need to exist there.
Leaving the cluster does not require abandoning governance
Moving a static page away from self-managed infrastructure does not mean throwing a folder somewhere and hoping for the best.
I still need to preserve:
- the versioned source of the content;
- a reproducible build;
- validation before publication;
- protected evaluation versions;
- a correct domain; a connection encrypted by Hypertext Transfer Protocol Secure (HTTPS); response headers—metadata that guides caching, security, and browser behavior—and search indexing—the conditions for search engines to discover and include the page;
- metrics under a privacy policy;
- publication history;
- a verifiable way to return to the previous version;
- a portable copy of the result that can be served somewhere else.
What changes is the operational responsibility.
Instead of maintaining machines, processes, an internal network, and routing merely to deliver files, I send the artifact to a surface specialized in distributing them. A content delivery network (CDN) keeps copies near different regions and responds without making every visitor cross my private infrastructure to retrieve each file.
That exchanges one dependency for another.
It does not eliminate risk or turn the provider into a divine institution incapable of failing. The new platform can suffer outages, limits, pricing changes, configuration mistakes, or account blocks. The domain and the system that translates names into internet addresses—the DNS—still matter. The publication process still needs security. An overly proprietary function can recreate the coupling I was trying to remove.
This is why artifact portability matters.
If the final result is a standardized folder of files, I can test it locally, compare its contents, and publish it elsewhere with less rebuilding. If every page depends on a provider-specific function, I have merely changed the cluster’s name in the diagram.
The dynamic part can remain dynamic without holding the entire page hostage
A static interface can still submit a form, call an interface through which systems integrate—an API—load authenticated data, or start an automation.
Those operations are dynamic.
They need validation, limits, abuse protection, secret handling, safe records, and predictable behavior when the destination service is unavailable. In some cases, a small function running only on that route is enough. In others, there is a complete system behind it.
The difference is that the entire page need not be generated by that system merely because one button talks to it.
I can separate:
- the public presentation, built in advance and distributed as files;
- dynamic routes, executed only when a real action occurs;
- private systems, kept outside the browser’s direct reach;
- failure behavior, which reports the problem without pretending the action succeeded.
This separation does not keep everything working through every incident. If the subscription API goes down, subscribing may be unavailable. But the site can still explain the service, show an alternative channel, and state clearly what did not work.
Availability need not be binary. One part can degrade without taking everything that remains useful with it.
How I decide whether a site can leave this path
I do not start by asking which platform is fashionable. I start by inventorying what happens when someone accesses each route.
- Does the HTML change for every request? If the content is identical for everyone until the next publication, it is a strong candidate for construction in advance.
- Is secret or personal data being processed? If it is, that data cannot be pushed into the browser merely to call the architecture static.
- Does the content need the server, or do only the actions need it? A dynamic form does not force every page to depend on the same execution environment—the runtime.
- Can the result be tested as an artifact? I want to open the generated folder and validate links, language, metadata, accessibility, and behavior before sending it anywhere.
- Is publication reversible? A new version must be able to fail without destroying the previous one, and returning must be more concrete than “the platform probably keeps something.”
- Does the destination introduce unnecessary proprietary dependencies? Functions, databases, and specific resources enter only when they solve a real requirement.
- What happens during a partial failure? Does the page remain readable? Does the action disable honestly? Is there an alternative channel? Is the error observable without exposing sensitive information?
- When does the migration end? After testing, an observation period, and confirmation of the return path, the old infrastructure must be retired. Otherwise, “simplification” ends up maintaining both architectures forever.
That last item is less charming than the migration diagram.
It is also where actual savings and risk reduction finally appear.
What this case does not allow us to conclude
I am not proposing that every application become a collection of static files.
A transactional system, an authenticated area containing sensitive data, an application assembling request-specific responses, or a product depending on server logic still needs a dynamic layer. Depending on latency, sovereignty, integration, cost, and control, self-managed infrastructure may be the better choice.
Nor am I claiming that single-page applications—SPAs, which update the browser interface without loading a new document for each interaction—automatically solve search indexing, accessibility, or performance. A site can be static and still be bad. For public content, generating HTML in advance may be better than delivering an empty page that appears only after a large amount of JavaScript runs.
SSR is not waste by definition either. It is waste when we pay its execution complexity without satisfying an application need.
Finally, a managed platform does not remove responsibility. I remain responsible for deciding what I publish, checking the build, protecting dynamic routes, limiting dependencies, and maintaining an exit.
The thesis is not “outsource everything.”
It is “do not force a finished page to depend on an entire factory still running.”
Mature architecture is not the one with the most boxes
I like infrastructure. For years, I have crossed the entire pipeline from requirements to software, publication, monitoring, security, backup, and continuity.
Perhaps that is precisely why I am less interested in keeping a component merely because I know how to operate it.
Technical knowledge should not increase the amount of technology I put into every problem. It should increase my ability to distinguish what is essential, what is contingency, and what has become architectural decoration.
A cluster is an excellent tool when there is work for a cluster.
SSR is an excellent tool when something needs to be rendered on the server.
A static site is a mature solution when the requirement is to distribute, safely and predictably, something already finished.
Resilience is not counting how many boxes appear in the diagram.
It is knowing how many can fail without taking down what should have remained available.
At i-9.ai, this is the kind of question I prefer to ask before adding another layer: what capability does the system actually need—and what responsibility can we remove without losing control?
If your company maintains an entire architecture to deliver something that could already be finished, get in touch. The conversation can start with the actual path of each request, not the tool someone decided to place in the diagram.
Continue reading
- Technology’s evolution: from the mainframe to the infamous real-time pun: a walk through the abstractions that brought flexibility—and the responsibilities that remained.
- Your company does not need to discover where to put AI: a method for starting with the problem and choosing only the capability it requires.
- I was born in 1986 and survived at least nine ends of the world: why important changes need method, backup, and direction rather than panic or euphoria.
- The best answer is not the one that pleases me most: how to turn judgment into infrastructure without hiding inevitable dependencies.
Learn more
- Static web page: an encyclopedic overview of pages delivered without dynamic generation per request.
- Server-side scripting: context on generating content on the server rather than in the browser.
- Content delivery network: an introduction to distributed points that deliver files closer to readers.
- Computer cluster: an overview of machines coordinated to work as one system.
References and limits of use
The sources below support specific technical mechanisms and principles. They do not prove that a managed platform will always be more available, cheaper, or more appropriate than self-managed infrastructure. The decision described here is an authorial synthesis applied to cases where content could be built in advance.
- MDN, “What is a web server?”: distinguishes servers that deliver static files from those that run software to generate dynamic content; it does not prescribe an architecture for a specific product.
- MDN, “The web standards model”: explains the structural, presentation, and behavior roles of HTML, CSS, and JavaScript in introductory language.
- MDN, “HTTPS”: defines the protocol used to protect communication between browser and server; it does not prove that a specific deployment is configured correctly.
- MDN, “HTTP headers” and Google Search Central, “How Search works”: explain response metadata and the general stages of discovery and indexing; they do not audit the publication discussed in this article.
- Google SRE, “Addressing Cascading Failures”: describes how dependencies and overload can propagate failures; applying that principle to removing the application server is this article’s architectural synthesis.
- React, “Quick Start”: introduces components as reusable pieces of an interface; it does not determine which publishing architecture a project should use.
- W3C, “What is Internationalization?”: explains how products are prepared for different languages, cultures, and conventions; it does not assess the specific implementation discussed in this article.
- Kubernetes, “Replicas”, Cloudflare, “Load Balancing”, and Google SRE, “Monitoring Distributed Systems”: introduce application copies, traffic distribution, and operational-signal observation, respectively; they do not make these components necessary in every architecture.
- Vite, “Building for Production”: documents that the default build produces a bundle suitable for static hosting; it does not guarantee the quality, search indexing, security, or portability of every application built with Vite.
- React, “Server React DOM APIs”: documents APIs that render React components to HTML on the server; it does not claim SSR is mandatory or unsuitable for an entire class of applications.
- Cloudflare Workers, “Overview”: introduces the runtime, its capabilities, and static asset delivery. This page does not document the OpenAI Sites package rules: that passage is limited to the installed version 0.1.46 and the author’s three observed runs.
- Cloudflare Pages, “Limits”: identifies the current Free-plan limits cited in the article; availability, quotas, and terms may change and must be reviewed for a future decision.
- MDN, “DNS”: defines the domain name system and its role in associating names with resources such as IP addresses; this glossary supports only the technical definition, not a DNS architecture or the article’s broader thesis.
- MDN, “API”: defines an API as an interface of rules and features through which software interacts with other software; this glossary supports only the technical definition, not the availability of the integrations mentioned.
- MDN, “SPA”: defines single-page applications and notes general advantages and disadvantages; this glossary supports only the technical definition and does not prove static HTML is superior for every product.
- MDN, “JavaScript execution model”: abstractly describes the basic infrastructure of a JavaScript runtime environment and the cooperation between engine and host; its scope does not prescribe how every runtime or architecture should be organized.
- Google, “Site Reliability Engineering—Simplicity”: supports the operational relationship among simplicity, loose coupling, comprehension, and reliability; its examples come from Google’s context and are not a universal availability guarantee.

Open conversation
Continue the conversation
Disagree, spot a gap, or have an experience that adds to the subject? Comment with your GitHub account. Do not publish personal data, credentials, or sensitive information.