I feel like there's a large class of tools in this space now (Vercel, Netlify) that do all of this and more, and this post is less about Cloudflare Pages and more about the (really good) state of static hosting these days?
Static hosting combined with server-side dynamic content modification using postgres was the interesting part for me.
Static hosting has historically been seen as exactly that, static and immutable.
Things like Cloudflare functions/workers can turn static hosting into dynamic content delivery while maintaining (most of) the benefits of static hosting.
Granted, this can be done whether the underlying content is hosted on Cloudflare, AWS, or a server in your garage so long as it’s proxied/CDN’d by a service like Cloudflare or Cloudfront+Lambda@edge, etc.
Yes, it's great because static/static+some dynamic bits fits a lot of use cases and it's quite simple to deploy, manage and maintain.
It's nothing that new though, Firebase (part of GCP) and Netlify have had that for years. CloudFlare just have the right combination of marketing, reputation, pricing and tech to make headlines with it again.
> Yes, it's great because static/static+some dynamic bits fits a lot of use cases and it's quite simple to deploy, manage and maintain.
Do you have some examples? I always get excited by this serverless stuff, but often the use-cases are quite limited if you think about it, or maybe I’m thinking wrong, especially if you take vendor lock into consideration.
Contact Form - Comments System - Authentication System - Image resizing (thumbnails) - GraphQL Gateway (working on this now) - Bypass CORS - Generate a random number on the server
I also built full apps on CloudFlare workers (and doing it now).
Only one caveat: They are heavily invested in marketing but their tooling is real cr*p. They are not investing in the Rust integration; or the more regular tools/integrations you are used to.
This comment is about serverless in general, not this particular tech. I’ve been abusing serverless for three years now using a NestJS bridge to the API gateway. All API request get bulk routed to a single lambda. NestJS, a dependency injection system for Node, handles particular routing, JWT validation, etc. Then my code does all the backend stuff. If I ever need to move from AWS lambda to EC2 (due to payload size or sync call limitations), I can. Neat JS will boot normally. Little to no vendor lock-in, especially in the domain later thanks to Clean Architecture.
I have never seen an example where you land a JS file in a static website in git and it just runs as part of server side middleware. Seems legit novel but would like to know other examples.
That's not middleware, is it? It's cool, but sits between what is discussed here and something like a FaaS. My understanding is that this post is about actually deploying middleware that runs during the serve of the static pages.
You drop a file in the functions dir of your repository, edit the firebase.js(on? it's been a while) config file to say that function X maps to path Y (so you can have api.site.com or site.com/api or whatever you want as a redirect to your function), and run firebase deploy.
It's similar to what I was doing 10 to 5 years ago but in Perl.
Drop a file into a directory which is all or mostly static Markdown, HTML or CSS, but those files can contain markup to call other modules, as well as code files.
The existence of a file is enough for its index code to be run (if it has any) and any URL-set and page components it makes available are available to other pages to be used, or served as they are. A single file can offer many URLs, usually anchored at the name of the file but not necessarily. The reason it can affect URLs outside the name of the file itslf is that it's efficient to index all files in a directory tree, even on every HTTP request, if that's done by file change detection and the results are efficiently cached.
Some of those files act as filtering middleware, processing the input and output of some or all URLs and passing along what they don't change.
Updating static Markdown, HTML and CSS, dynamic content, code, and JSON data, are done by 'git push' or 'rsync', or just by editing files in place if you prefer. The server automatically detects file changes and keeps track of all code, file and data dependencies when individual things are used to calculate a response. The full dependency structure for each response calculation is recorded with each cached response.
Cached responses include both full HTTP responses, and components and data available for use in the manner of a subrequest. If a previously cached response depends on a file that has since changed, or been removed, or even a file that was previously absent but now present, or another cache condition such as a JSON or SQLite file change, or logged in user etc, the cached response is invalid and must be regenerated. Regeneration is a combination of on-demand and ahead-of-time, to be able to respond quickly with the speed of a static site for small finite page collections, while behaving correctly with large or infinite collections. Some code updates trigger a process restart because some code can't be safely unloaded or replaced; some code is fine updated, though, and this entire process is well automated. In practice, pleasant and fast to use: edit a file and see the result immediately on reload, with no compile/build step or extra actions.
The dependency structure partly reaches the browser, so that requests to cached responses can be served more efficiently, sometimes even zero latency. In some circumtances, changes in files cause events that ripple through to the browser causing real-time updates to components in-page without a refresh. The result of those is a little like Meteor or LiveView, except almost everything is made from static page files in Markdown or HTML, code files, and JSON data files, and the set of available pages (and "table of contents" pages) are built by indexing those files.
In practice it's mostly writing Markdown, and this is great for emphasis on content first. Or Markdown templates: content that varies a little according to data. But with extensions to be able to drop in useful rendered components (graphs, generated images, templated CSS, transclusions for headers/footers, etc) and dynamic components (live updating when the underlying data files are edited).
It even serves PDFs and thumbnails of those as in-page components, where the PDF content is HTML rendered by running Chrome on the fly from within an in-page component to generate the PDF or image, with Chrome told to fetch a subrequest which serves it the contents of that very same component. This makes for some pretty lists of downloadable PDFs, all generated from JSON data. This probably sounds complicated, but it was actually a fairly simple single file of code, dropped into a directory to make the component available by name inside the other Markdown quasi-static files.
One small VM served a few thousand requests per second last time I checked. Not as fast as a Rust server, but good enough for my uses. It made heavy use of Perl coroutines to serve and cache concurrently, and NginX to make routing and static-serve decisions. Perl coroutines are not commonly used (for ideological reasons I think), but they work very well.
I don't use the sytem any more, but it was the nicest I've used.
Cloudflare workers are distributed through hundreds of locations, and thousands of servers. Doing that with Perl would have been impossible. Also, remembering from my old CGI/PHP days, what usually happen is that the scripting language creep start getting bigger and bigger until it's unmanageable.
I'm not saying Cloudflare workers are a better proposition now. (their ecosystem is a complete shitshow) but the idea has lots of potential; and will probably be the future of computing[!].
!: That is, if the decentralized web fails to take off in the next 5 years.
I think you're right, but I think the key part of the tech is economic: their ability to deploy hundreds or thousands of instances safely shared by large numbers of replicated sites and applications belonging to different site owners.
Individual site owners can't afford that level of infrastructure for each site separately. Actually deploying it isn't that difficult, it's just expensive and unjustifiable.
(I nearly started a business doing what Cloudflare Workers is doing now, about 10 years ago (and not with JS/Node), so I know a fair bit about building out this sort of distributed edge system, including the WebSockets and anycast part. But life took a turn and IPv4 blocks for anycast were starting to look a bit beyond what I could justify for the development, even back then. In retrospect it would have been a good thing to build.)
> That is, if the decentralized web fails to take off in the next 5 years.
You have given me an idea :-)
(For a side project I'm working on zero-knowledge proofs of execution, which allows nodes to execute code on behalf of other nodes without the latter having to trust the former. Performance is far too slow to run things like websites at the moment, but there are many tricks for speeding it up, including hardware acceleration.)
> Cloudflare workers are distributed through hundreds of locations, and thousands of servers. Doing that with Perl would have been impossible.
No, it wouldn't, that's a misconception. The Perl system I described ran fine on however many servers you wanted to run it on, like any horizontal scaling system. Pretty much anything that runs in a container and isn't required to communicate with a central database does. The design based around indexing files and caching calculations is effectively stateless; it scales without limit if you have the servers.
Any specific points of global data consistency require communication with a shared data store of some kind, but that's also true in Cloudflare workers, where there's a separate Durable Objects system for that. Cloudflare's Durable Objects is pretty good as those things go, but that's not what your comment was about.
What's impossible for most is paying the cost of hundreds of locations. And if you really want to do it well, anycast IP blocks. But if you have the servers, and don't need every request to fetch from a central database (or can use an eventually consistent distributed one), there's no problem deploying as many instances as you want with something that's effectively stateless, even if it's Perl, Python or PHP.
> what usually happen is that the scripting language creep start getting bigger and bigger until it's unmanageable.
Probably right, but I'm curious why you think there won't be equivalent JavaScript creep in sites using CloudFlare Workers.
I'm interested in why you think that their ecosystem is bad. I was going to tinker with it. Also, do you know alternatives in the space that are better?
It’s not. You can achieve the same or better results with Varnish. You can even achieve edge caching with Fastly (cloud varnish).
I think of it just as a different approach, where the focus is static (cache) with dynamic layered in as necessary. This forces you to be more explicit about dynamic behaviour and treating cache as a priority concern.
This is exactly how we built Bluo: dynamic cms just like wordpress that deploys static assets (html,css,js,images) to cf workers.
Benefits are obvious: high reliability and speed to serve the static files. In addition, if the cms server is down for whatever reason, your website is still live and working fully (not just cached pages, all of them) just fine.
Actually you can think of it like a pre-built cache that it’s deployed to cloudflare kv store.
Other cool features we have is real time collaboration in the editor.
Can you explain how Cloudflare Workers factor into hosting static pages on Cloudflare Pages vs hosting a React SPA on pages that talks to any other API?
Like are the workers just serving as your backend at that point? Or are they doing something more or different as well?
Ah, so still fully static vs. a SPA that uses REST or GraphQL. So then clients interact with it as static HTML/JS rather than hydrating it via Javascript.
No it’s pointing out the server side scripting part which was new to me. do analogs exist in those other hosting options? This seems like a really nice facility - closest analog client side wise is a service worker or something that adjusts fetch.
Author here. I actually thought about using this library. In my case re-rending as svg was too complex. Much more practical to upload screenshots of DOM, share those via functions/middleware.
I’m happily using CloudFlare pages. The reason I haven’t tried Netlify is that after the free tier everything seems a little overpriced. I didn’t go for Vercel because I don’t want to use Next.js and I’m afraid I’ll run across some limitation because of this. I was already using Cloudflare as a CDN for S3 and GitHub pages, and their offerings seem to be growing quickly and wanting to compete with Amazon rather than the static hosting companies.
All of the Vercel platform features you can use in Next.js (or other frameworks) are also available through the Build Output API for frameworks to target. This is what frameworks like SvelteKit, Nuxt, Solid, etc use on Vercel.
If you don't want to deal with any of that but like MDX (think Markdown with the option of JavaScript), I believe motif.land publishes your MDX sites with Vercel.
What is really annoying is that Cloudflare pages will strip the file extension off of your html pages, and perform permanent redirects to those new URLs. Now if you're intending on moving to a new hosting service that doesn't do that (cgi-bin), all Google search results to your site will 404.
Github pages and likely others also supports this format, so moving between those two services doesn't exhibit this problem. Moving to cgi-bin will.
I'd suggest Cloudflare shouldn't try to establish their scheme as canonical url and rather implement github pages behavior, but what do I know... I'm just hosting an old fashioned blog, not a JAMstack/SPA/whatever thing
Having .html file extensions is very old school, and its removal is one of the popular/default redirects on all http servers that support it. Site generators also hide it through various methods (e.g. having a folder with the path name with just an index.html where a dynamic redirect isn't possible).
It was removed explicitly for SEO and having a single canonical URL for a resource _for all of time forever_. Right now we use HTML for web pages but who knows what the internet 20, 50, 100, etc. years from now will use--maybe .Super-Awesome-Mega-HTML is all the rage. If over time you are changing your site and its URLs are changing then you're breaking that canonical URL and search indexes, caches, way back machine, etc. all suffer. So the intent is don't make the format of the page (HTML) part of it's canonical URL.
The benefits aren’t just SEO. I’d much rather have /about than /about.{htm,html,php,asp,etc}. I don’t see how the latter is preferable for routing to pages.
I second this. That's what mime-type headers are for. The URL should locate a resource, as the name suggests, not necessarily convey metadata about what the resource is.
Maybe this is just me, but I like that I can decouple the way I organize my file system from the way users access my site. And with that comes the ability to get rid of file extensions and make urls more human-friendly. Remember, not every person has file extensions turned on by default on their Windows File Explorer!
Do you have experience running websites that cater to the non tech savvy? How are your urls set up? Do they get confused where to find things? Do you use a database? Do you dynamically render content using templates?
Not the GP here, but having run websites for the non tech savvy I can say they have no problems with any sort of URL structure because they are oblivious to URLs. They enter your-site.com into Google, click the first result (even if that’s an ad for your competitor), and then click round the links presented.
The user presumably wants to know what kind of content they're going to receive from a given endpoint - foo.html, foo.pdf, foo.jpg, foo.mp3 and foo.avi suggest quite different experiences, and it's nice to include that hint in the URL (where it's visible on mouseover) rather than the user having to go in blind. I also like being able to reassure the user that they're receiving the same piece of content however they access a given resource, rather than the possibility of invisible content negotiation changing the site's behaviour.
Such hints can be unreliable at best and misleading at worst. There is nothing to guarantee that the file extension and the Content-Type header will agree, nor is there anything to guarantee that the file name in the URL will match the download file name in the Content-Disposition header.
Well, sure, but you can just... not do that? The <title> tag can be misleading because there's no guarantee that the title matches the content of the page - but the answer to that is to use good titles for your pages, not to avoid using the <title> tag.
My point is that it isn’t really reassuring for the user because of invisible negotiations. If anything, I would lean more towards guessing that users are, more often than not, either ignorant or untrusting of URL contents, either because the URLs so frequently look like nonsense (arbitrary content IDs instead of meaningful names) or because they have already proven to be unreliable elsewhere on the web (deep links not as deep as expected when copied or shared).
> If anything, I would lean more towards guessing that users are, more often than not, either ignorant or untrusting of URL contents, either because the URLs so frequently look like nonsense (arbitrary content IDs instead of meaningful names) or because they have already proven to be unreliable elsewhere on the web (deep links not as deep as expected when copied or shared).
I think users are (rightfully) distrustful of URLs in the general case, but a URL having a file extension is actually a pretty good indication that it's a simple "does what it says on the tin". (Imgur changing their .jpg URLs to have more complex behaviour caused a pretty big backlash, for example)
I guess no one should know whether a pdf is a pdf. Or even whether it's a .com or a .org domain - the browser should just strip all that confusing stuff away!
When you're serving someone an HTML file are you serving them the exact copy on your file system or do you ever use templates? Do you ever pull info from the database? If so, can you see why this is slightly different from directly serving a static pdf?
Also note that you'll often see a PDF generated on the fly with a long, difficult to parse URL.
Take up your second point with the W3 or whatever, to be honest if tlds weren't so important for phishing and whatnot it would probably be fine. I think some browsers have started doing that anyway. You overestimate how tech savvy the average user is, and by extension you overestimate how much the average user can keep track of all this complexity. Do you think most people have heard of .info or .xyz?
That's what mime-type headers are for. The URL should locate a resource, as the name suggests, not necessarily convey metadata about what the resource is.
My web server is not exposing file system paths to the user, it is deciding on content programmatically and it’s purely an aesthetic coincidence that the url path looks like a file system path.
I exactly ran into this issue when migrating from a different provider to CF pages.
I preferred to strip away the .html extensions anyway, so it was okay in my case. CF should trigger a HTTP 308 for older .html to the new urls automatically.
You can use the more barebones Worker Sites and retain file extensions. Pages has nicer UX (automatic PR preview sites!) but the old school Worker Sites setup is dead simple and does exactly what you want - it's just a template setup to load assets from KV storage.
Maybe I'm misunderstanding, but Apache httpd has performed URL rewriting such as adding a .html suffix after mapping URLs to file names where appropriate, and other transformations such as content negotiation for languages, spelling correction, etc. for ages.
Cloudflare automatically redirects any /foo.html URL to /foo, with a permanent redirect. That is certainly not standard behavior, neither on httpd nor gh pages
In 10 years time when cloudflare goes bankrupt/withdraws the free offering, will you be able to redeploy to another platform or will you start having to delve into 10 year old code and porting it to a new API?
Is there at least an nginx-cloudflare module that lets you self-host this stuff?
You mostly use standard Web APIs inside Workers, so that's portable, but the entire runtime (including Durable Objects, KV, R2 and D2) is open-source and can be self-hosted.
The static part, certainly (aside from issues like .html redirects, etc.). The dynamic part, hopefully with minimal work assume you can find a service that offers the same features, plugging into a new interface shouldn't be difficult.
Why not just make it CGI (or FastCGI) compatible so you can test it locally or run it in other environments? At least for things that are actually generating responses rather than acting as middleware.
We did not create our own engine to create "lock-in". On the contrary, it would be a huge win for us if we could simply run FastCGI or Node or whatever applications unmodified. We'd be able to onboard a lot more customers more quickly that way! Our product is our physical network (with hundreds of locations around the world), not our specific development environment.
But none of that tech scales well enough that we could run every app in every one of our locations at an affordable price. Meeting that goal required new tech. The best we could do is base it on open standard APIs (browser APIs, mostly), so a lot of code designed for browsers ports over nicely.
(I'm the lead engineer for Workers. These were my design choices, originally.)
Hey, just wanted to leave this here. It’s pure joy to work with Pages. I recently did a new homepage for my mom‘s beauty salon and decided to use CF Pages, with a few functions for booking requests and a contact form. It felt just… right. Everything fell into place as I would have liked it to. Hits the sweet spot between flexibility and pragmatism, in a way.
Are there guides for application architecture with Workers?
I'm interested in Durable Objects but I don't know how to work within the 50-subrequest limit on the Free or Bundled plans.
It sounds like I can only read from 50 Durable Objects or KV queries in a single request. If my usage pattern is e.g., sharing docs with many users, how would I let more than 50 users access a doc?
Whether I consider fanning out on writes or fanning in on reads I'd need more than 50 subrequests. How should I approach this?
Hmm, I think there are several different reasons why the subrequest limit actually doesn't apply to your scenario.
First, Durable Objects and Workers KV requests do not count against the 50-subrequest limit. It's HTTP requests to external servers that count.
Second, with the Unbound billing model, the limit is now 1000. The old "Bundled" billing model is really intended for "configure your CDN" use cases where you're mostly just rewriting a request or response and proxying to origin. For whole applications you should use Unbound. (Note that with Durable Objects, the objects themselves always use the Unbound pricing model.)
Third, to address your specific scenario:
> If my usage pattern is e.g., sharing docs with many users, how would I let more than 50 users access a doc?
If you mean you have 50+ users connected via WebSockets and you need to send a message to each one -- these messages (on already-open WebSockets) do not count against the subrequest limit. Only starting a whole new HTTP request or new WebSocket would count.
And for "fan in", these would be incoming requests from client, but the subrequest limit applies to outgoing request. There's no limit on number of incoming requests.
> First, Durable Objects and Workers KV requests do not count against the 50-subrequest limit. It's HTTP requests to external servers that count.
Ahhh, somehow I got the idea that requests from a Worker to Durable Objects and KV counted against subrequests. This changes things!
> If you mean you have 50+ users connected via WebSockets and you need to send a message to each one
I was thinking of, a client requests "give me a list of my documents" or "share this document with Alice, Bob, et al.", and the Worker that receives that request has to handle that somehow. I thought that was tough to do in 50 subrequests, but it's easy if I can just make an unbounded number requests to different Durable Objects or KV records.
Edit: I found what gave me the idea about subrequests. From the Workers docs:
> For subrequests to internal services like Workers KV and Durable Objects, the subrequest limit is 1000 per request, regardless of usage model.
Because V8's low-overhead tenant isolation is fundamental to how Cloudflare Workers works[1], and without it it would be a completely different product with worse performance. This means it can only support JavaScript and WebAssembly.
You can run it locally[2], and efforts are underway to standardize much of it so that the same code can run on Workers, Node.js, and Deno[3]. The Workers runtime is also open source[4], although in practice this is likely to be less useful for most use cases than just using one of the other JavaScript runtimes if you're self-hosting.
For better or worse fast CGI never took off much beyond PHP. Python, node, ruby, etc. all do their own thing with their own app servers and protocols. I mean sure something like python can use fast CGI but no one in that community uses it that way, everyone uses uWSGI, gunicorn, etc.
Plain old CGI doesn't scale beyond toy usage--it spawns a process per request.
So there really isn't a good single option for Cloudflare to use.
> Plain old CGI doesn't scale beyond toy usage--it spawns a process per request.
I'd be willing to bet the opposite: CGI is more than enough for 80% of workload, performance-wise.
There are a few good reasons why CGI isn't the best today: the tooling doesn't exist, the security model is really bad, and you can cram fewer websites on a single machine, so for the same number of websites you need more machines, and that's an ecological aberration. But there is no problem about CGI being too slow.
What do you think is the upper limit of requests per second, if your HTTP server does process-per-request? For simplicity, assume server class hardware, that each request does no work besides producing a response, and an upper bound of 10k unique remote addresses (i.e. no more than 10k concurrent connections in a different model).
How do you think those metrics compare to other designs? I have an affinity for the conceptual simplicity of CGI but I've never been able to get a process-per-request server within even an order of magnitude of the performance of the more common designs. But I could be missing something!
> What do you think is the upper limit of requests per second, if your HTTP server does process-per-request ?
In the hundreds, which is absolutely enough for most use cases. If CGI is enough for sqlite.org displaying dynamic content (such as in https://www.sqlite.org/cgi/src/timeline), it is enough for 80% of websites. You are not bigger than sqlite.
> How do you think those metrics compare to other designs
The important question is not "is it better or worse than alternatives" but "is it enough for me". Yes, it is.
> Also, how does this design adapt to HTTP/2?
HTTP/2 doesn't change anything. Requests are on the same socket until the webserver, and the webserver forks a process for each request, multiplexes the responses and all is well.
> The important question is not "is it better or worse than alternatives" but "is it enough for me". Yes, it is.
All good! But if you're OK with O(100) RPS out of a server, then I guess basically every possible option is on the table. I bet `nc` spawning background `bash` scripts to handle requests would get to 1k RPS, even! ;)
> HTTP/2 doesn't change anything.
I guess that would work, as long as the fronting server managed all of the connection management details, stream demuxing, etc. But I wonder how you'd do that in a single thread?
It is indeed very very slow; mostly because it is not possible to pre-fork your CGI scripts (environment variables get set from the request, so each cgi program will have different values in the environment).
But, if you could pass HTTP data via some way other than environment variables, you could pre-fork the binaries and have acceptable speed[1].
Sure but developers don't want to bifurcate their service code and releases into a simple version using CGI and a dedicated app server version for when CGI doesn't scale for them or their users. They just want to write one python web app and run it everywhere.
There's no way a CGI app can reach a million requests a second on the same hardware that a nodejs (single thread, worker loop) would take to do 1M RPS. Processes have a lot of overhead. Almost no one needs 1M RPS but it cannot be waived away that CGI is perfect for everything.
That's the problem: people absolutely exaggerate how much their site will need. I didn't say CGI is perfect for everything, I said it is enough for 80% of the websites, for the entire lifetime of said sites. Your blog won't suddenly reach Alexa top 100. Your family sharing photo site will remain seen by your relatives only. You HOA website won't become a trending topic overnight.
Yep. Also, sharing resources between connections is (at best) very difficult using CGI, and its trivially easy using a stand-alone app server. You can just set up a global variable at process startup and you're done. (This is useful in just about every web app I've ever written - eg for the connection to a database, cached resources, cached renders of common pages, in-memory only security tokens, etc).
I also find the modern approach much easier to reason about and debug. I don't need Apache + fastCGI + php + php fastCGI + apache configuration to get started. I can just run `node server.js` and my web app works.
The fact that it also scales much better is a cherry on top.
> Also, sharing resources between connections is (at best) very difficult using CGI, and its trivially easy using a stand-alone app server. You can just set up a global variable at process startup and you're done
You can pass environment variables to CGI scripts as well. In fact, that's exactly how CGI works. Shared resources can be cached in memory through redis, although a shared file (for example sqlite) is enough in many cases.
> I don't need Apache + fastCGI + php + php fastCGI + apache configuration to get started
Again, I'm not saying CGI is the fastest but that it is fast enough. Opening a new connection (or better yet, using SQLite), reading a file that contains a prerendered HTML string are fast enough for most use cases
Forgive my digression but for years I’ve seen small efforts here and there to elevate the concept of a “stack” and promote it as the level abstraction to use when discussing web apps and the like. What’s up with that?
Grab any 3 commonly used pieces of technology whose names can be used to form a fun initialism, append stack to the end, and soon there will be experts speaking at conferences dedicated to it. JamStack is an example you mentioned. I’ve heard others over the years.
I disagree that it’s a useful unit of thought. No one I know or work with ever talks about “web stacks” this way. Am I missing something here? Is this just some kind of niche? Who’s marketing these?
Jamstack in particular is not really an example of that; it is more of a kind of architecture than a specific stack, in that it doesn't prescribe the use of specific software. An architecture where all the HTML/CSS/JS is precompiled statically for maximum cacheability, and server-side dynamic behavior happens exclusively within AJAX calls that return structured data, is a natural kind, and useful to have a term for so that we can compare and contrast it to other ways of building web apps.
More broadly, other acronym stacks are a thing because complementary technologies cluster together, especially in relatively immature ecosystems. E.g., PHP traditionally had better support for mySQL than for competing databases, so if you were building an app in PHP, you probably used mySQL for data storage. These effects may have weakened over time as the graph of ecosystem integrations has grown more complete (and indeed I feel like I hear less about acronym stacks these days than I did half a decade ago), but I don't think they've died out entirely.
The reason why PHP was bundled with MySQL historically is not so much because it had better support for it, but rather because cheap & free hosting would generally offer MySQL (rather than, say, Postgres) - because it was easier for them. If SQLite showed up a bit earlier, I bet that would have become the standard.
What else would you call the well, stack, of technologies used to host a website? It's not a marketing term, just a way to describe the multiple layers. From hardware to network routing to DNS to tcp/up to http to https to HTML to JS to workers, and also Linux and PHP and a web server like Apache or nginx and a database like Maria or Postgres and maybe a cache like Redis or memcached and maybe squid and Varnish in front of it... that's a stack.
Jamstack is just a particular configuration where vendors take care of all of that and you can push up frontend code that auto deploys and that's that. I used to have to manage the whole stack and now can work purely in HTML CSS and JS and it is a DREAM. That's the magic of the Jamstack. Less devops and network infrastructure, more time to focus on UX and DX.
As for vendors, there's Vercel, Netlify, Gatsby, maybe a few others. Cloudflare, Deno, and Fly, Render and a few others have similar variations.
Cloudflare Pages and Workers (and similar products) are indeed great but I recently switched over to a plain old free tier Oracle Cloud VM with FastAPI behind Nginx (Docker containers). I use Cloudflare as a proxy for HTTPS/certs. I don't have to think about Cloudflare Worker limitations, can host a Postgres instance, and simply deploy through `git pull` and `docker-compose up`.
> As a shortcut, I used GPT-3 to generate a basic typescript function for me. This let me look at TS type definitions and get a better idea of what’s available so I could get developing.
As a long time programmer, I keep trying to maintain my skepticism of AI/ML techniques for program authoring. Comments like this are dissolving my
objections by the minute...
I don't know which GPT-3 tooling they were using, but Github Copilot can be _exceptional_ at generating rubbish. Autocomplete, at least for me, was seldom even syntactically correct, and never semantically correct.
They have a product for that https://www.cloudflare.com/pg-lp/speed-up-wordpress-with-clo... It caches all pages on Cloudflare and only bypasses Cache on Cookies such as `wp-.|wordpress.|comment_.|wordpress_logged_.` which is used by /wp-admin/ are and when someone posts a comment. This turns your WP into static without doing anything special. Or you can write a custom cache rule for cookies using "Page Rules" or newly introduced "Cache Rules" beta https://developers.cloudflare.com/cache/about/cache-rules/
I used wp2static to archive a WordPress site recently, and I am disappointed with the performance.
The same website without Cloudflare CDN and just using a simple caching plugin is much faster than the exported version by wp2static hosted on Cloudflare pages.
It has fallen from 99 to 78 in the mobile page speed test.
I tried creating a copy of the website using wget, it was faster but i faced issues with missing files and posts on the main page using temporary query links and not the permanent links.
So I went through the Hassle of compiling wp2static and just eating the performance loss instead.
This would require you to host WordPress somewhere.
If you can host it on workers for example, you can get an entirety free, managed website just with one click(obviously someone would do a template to enable you to setup wp on cf pages if that was possible).
I keep seeing these 'JAMstack' sites are the new hot thing when a static wordpress site is enough and easier to update than 'JAMstack' sites, in reality these sites are just glorified HTML under a CDN.
I don't see the benefit of JAMstack when you can just place a static WP site under a CDN like Cloudflare and have all the benefits of WP and a CMS to edit content.
At least with Cloudflare they are more than just a CDN, others like Netlify and Vercel seem to be both over engineered and overpriced for what they do.
They solve different problems. WordPress is a full stack solution that's great for blogs and simple websites. The downside is that it's a lot of maintenance (requiring a LEMP stack) and not very portable. You have to copy over everything from the code to the database to the files to things like htaccess and nginx config. Hosts Like Pantheon and wpengine make that easier, but you're still bogged down by overhead. Scaling is really hard if mere caching doesn't work because you have to deal with Mysql replication and slaving. And what's really annoying about this setup is that you HAVE to deal with the whole stack. If the content writers want to preview their changes, you have to a clone them a staging environment. That means DB merges or overrides. And if you're simultaneously making other changes to the production DB, good luck reconciling the two.
Jamstacks really shine when you can decouple the frontend from the backend(s), because then you have an easily replicable single repo with nothing but code. You can deploy it to any Jamstack host with a push and they handle all of the scaling and https and caching concerns. And the backend teams, whether an in house endpoint or content writers working on a hosted headless CMS, never have to care about the stack.
A middle ground that's interesting to explore is using WordPress with Advanced Custom Forms as a backend plus a Jamstack frontend. ACF is still quite a bit more powerful than any of the headless CMS solutions I've tried, but it does mean you still have to maintain a LEMP stack, which is a headache in and of itself.
As much as I dislike it personally, WordPress’s admin portal and plugins like ACF (among others) are simply unbeatable when the end result is handing the keys over a client, both due to power and familiarity.
I wonder if that will change given enough time. I certainly hope so, but I would’ve guessed that it would’ve changed already, but here we are in 2022…
Static WordPress is possible - you can generate a static replica of your WordPress site and deploy that via CDN. There are some plugins that help you do that (Simply Static, WP2Static) but you need to also configure your whole infrastructure when using them, and the build process can be long and painful.
There are also managed services for doing this that take care of everything for you, from the WP hosting env, to the static hosting and CDN, along with replicating certain types of dynamic functionality on the static site like forms and search.
One example of this type of managed static WordPress hosting service is Strattic: https://www.strattic.com.
Have you seen Strattic? It's a static hosting service for standard WordPress sites (i.e. monolithic WordPress as opposed to headless WordPress), so the time has arrived (unless you meant "freely" as in "free beer" and not "without limitation). https://www.strattic.com
I've successfully run WordPress with the simply-static plugin, and a script to send to static hosting. WP run on an arm64 instance that was only started when editing was needed.
Besides WP, there are static CMSes that fit a modern workflow perfectly.
> I've successfully run WordPress with the simply-static plugin, and a script to send to static hosting.
Interesting, simply-static never worked for me, only wp2static did and it had a lot of bugs.
> WP run on an arm64 instance that was only started when editing was needed.
How do you do this?, are you doing some kind of webserver container run trigger? Or running it on a managed platform?
> Besides WP, there are static CMSes that fit a modern workflow perfectly.
Yeah but they aren't so customizable and flexible like WordPress, the goal is to be able to create a whole static site without needing to write anything manually.
Biggest advantage I find is pre-scoped request-level control over everything. When someone loads your page, every single asset request hits your worker. It's both extremely simple and exceptionally powerful. Choose which responses to modify, authenticate, proxy, redirect, or let through. All in a single file with a few dozen LOC. No complex pre-app devops, middleware or routing policies required (i.e. oh sorry that route is proxied by a lambda, or you should check the cloudflare dash there's a worker sitting in front of that).
Yes, there are a bunch of limitations - but in practice I quite appreciate the boundaries and the reasoning. There's also the portability question, but we're talking about PaaS. As someone who was using Firebase for many years, and static AWS + lambda prior to that I find this evolution entirely refreshing.
I've pushed 5 personal projects on pages since Jan and working on more. Most recently https://thesom.au/gh/cvms
Author here, went through your github. Cloudflare should post your code as reference architecture. Answered so many questions re proper app structure on CF. Really appreciate the amount of effort your examples will save me in future.
How does using GPT-3 make the types more visible? Feels futuristic but also incomprehensible to me.
> As a shortcut, I used GPT-3 to generate a basic typescript function for me. This let me look at TS type definitions and get a better idea of what’s available so I could get developing.
Hope the author responds, because that stuck out to me too!
My assumption was that their prompt was something like "typescript cloudflare function" and they just used the resultant code to see types in action inside their IDE.
I have been working on servers whether professionally as a software engineer or as a pre-teen making a The Simpsons fan website for a couple decades now. I have never once used that `cgi-bin`, never opened it, and still have no idea wtf it is.
In my experience it's this thing exclusively used in offensive security training/CTFs. Not really sure what the intended use is, but it sure gets owned a lot
To write functioning code, you need to know how to write functioning code.
The biggest issue with Copilot is that, to use it well, you need to know:
- How to write functioning code.
- How to quickly review other people's code for correctness.
- How to write good comments.
- How to tweak the ordering in which you write code such that it's easier for Copilot to understand.
- How Copilot and other GANs work, in general. An awareness that Copilot is built on GPT-3, familiarity with what that implies, and so on.
And if you don't, that results in the AI seemingly not working as well, which makes it easy to make the assumption that it isn't an incredibly useful tool. It is, it just has a learning curve measured in weeks.
I believe this is why we constantly have arguments on whether or not it's helpful.
Yes, the copilot UX is extremely detrimental to reputation of AI systems for coding. I think we need some UX work to better explain possibilities and limitations and programming will never be the same
The Cloudflare cloud experience is "being sold short by subpar documentation" right now because important elements of their ecosystem are being ramped up from beta status. They also have internal docs which aren't kept up to date with their actual product. I'd check back in a few months because their beta experience can be very touch-and-go.
Agreed. One area where it's maybe not sold short but just hurting the UX; it's not immediately clear from their documentation that certain NextJS features you get 'automatically' on Netlify/Vercel just aren't supported yet. For example, using any kind of dynamic routing (i.e. going to `/books/:id` directly rather than clicking through) doesn't work yet as there's no router available to tackle this for you. According to their Discord, it's in the works but it has been in that state for a few months already.
You can work around this with some Workers that capture the dynamic routes, request the nextjs html file and return that, but then you're using up your Functions quota as well.
I've noticed that Cloudflare documentation is lacking, but I rarely find information that is published on official sources that is out of date. I find the fact that there are two dozen sources of information out there for an AWS or Terraform configuration, but they're all still wrong because the API has since changed and the documentation wasn't cleaned up when the breaking change was made.
I have found that with Cloudflare's documentation that where it's lacking they have the ability to PR in changes and if you go back to a saved page, I've found them pleasantly updated numerous times.
Thankfully the cutting edge development is based off of open standards that you can easily build off of. I know personally that I've found most of the sticking points of developing against Cloudflare to be easily mitigated and just be an overall better experience as a customer than with another hosting provider.
It doesn't hurt that they aren't charging me all that much personally, but I have a day job that fills up the Cloudflare stock price just fine.
> The Cloudflare cloud experience is "being sold short by subpar documentation" right now because important elements of their ecosystem are being ramped up
Their docs are subpar because Cloudflare is just not interested enough in documentation improvements and is hostile to the people who are interested and who try to make the improvements.
I tried fixing a 404 in their docs once. This would have taken, you know, approximately 2 seconds with a real wiki or CMS[1]. What resulted instead was an excruciating back-and-forth that took 9 messages over a span of exactly 5 hours, ended in no fix, and a Cloudflare dev trying to "upperhand" me (in the vein of George Constanza's pre-emptive breakup—"I'm afraid that I am gonna have to break up with you"[2]).
Sure, Cloudflare team, there's nothing wrong, I guess, with choosing to believe in the delusion that a repo full of Markdown files and the GitHub generation's busted-ass PR-based edit workflow is an acceptable substitute, just like there's nothing wrong with writing your name with a pencil that has a brick taped to it[3].
The rest of the industry haven't even started figuring out what Cloudflare Pages Functions + Durable Objects can do. Workers can also send emails for free, and soon you will be able to process them as well with Email Workers. Cloudflare also doesn't charge you for egress either.
> The rest of the industry haven't even started figuring out what Cloudflare Pages Functions + Durable Objects can do
I was very excited when both of these technologies were first announced (years ago).
I tried them, immediately, then (during the initial beta). They were clunky, half-baked, and don't even get me started on the DX of developing against them. Literally missing from cloudflare's own CLI - the official docs described how to manually deploy via CURLing endpoints. It felt like manually FTPing files onto a server, like in the 90s.
Ok fine, this is an early beta, let's let this bake longer.
So a few months ago, I started a new greenfield project and once again decided to give Functions + Durable Objects a shot... and was astounded to find the exact same half-baked experience, where different "beta" versions of the CLI had to be installed in order to support the different endpoints, and these were in fact mutually-exclusive.
Cloudflare has some cool ideas, but they seem to like rolling out 70% of a cool idea and then moving into the next shiny thing without ever making the first thing actually polished and reliable. After wasting many hours with Cloudflare's DX, I decided to never waste more time with them as a development platform (vs an optimization layer / CDN / etc).
There's a huge amount of websites that don't need a CDN (my blog has frontpaged multiple times without one). And for many (all?) of the rest you'd be fine with 3-5 regions. CDNs increase latency for low-traffic sites.
Getting angry at people for using centralized solutions is not a way to win people over to your cause, and even many people who would prefer decentralized solutions are going to pick the easy route sometimes. If you're developing a web app, maybe you want to spend your time writing app code. People only have so much time in a day.
You go ahead and play "being decentralised" with your buddies while people in the real world just mind their own business doing whatever they need to do using the current right tool for the job(in this case Cloudflare being the tool).
People in the real world, who just cheerfully do business, with zero thought of impact or consequences of their actions beyond next paycheck, have put us in this awesome economic situation, we all know and enjoy.
Surely blindly pushing, yet another corporation into position, where they can lobby virtually anything, is awesome idea. (Nothing against folks from cloudflare. They seem all right, but they will get acquired and/or change leadership at some point).
In nature, a lack of genetic diversity in a species isn't typically much of a problem until there's an extinction event, and then it can be a big problem.
You might not feel the downsides of having a huge percentage of the internet going through a single provider until it's too late to change it.
I actually quite like Cloudflare, and I don't think they're purposely doing anything nefarious (just following incentives like everyone), but I think caution is warranted.
Identity as service is another category that's egregiously priced, and it's usually priced based on monthly active users too, which is the worst. It would be great to see Cloudflare disrupting that one as well.
This. At this point in everything being "cloud native" fewer and fewer people and orgs have any experience building internet networks - buying transit (circuits), peering, etc.
For players at Cloudflare, AWS, GCP, etc scale it's essentially free. The fact that many of them (other than Cloudflare) charge $0.08/GB or whatever for egress and that's just accepted because people think "that's what it costs" is wild to me.
My personal conspiracy theory of sorts is that many compute, storage, etc products from big cloud providers are essentially priced as loss leaders because while the average dev has some idea of what a GB of storage, GHz CPU, etc costs (because they priced a laptop) they have no idea how bandwidth and connectivity is priced at this level and cloud providers capitalize on that (somewhat understandable) ignorance.
Wouldn't surprise me if it were in Freakonomics, but there is always a weird "charging point" for things based on old expectations that subsidies the enterprise.
Like the old 50c/m mobile phone calls, the 10c SMS messages, then when they were free, charging for international SMS and calls, now charging for data. It is the "whales" who spend a lot of money on mobile games. 1% fee for looking after your money, Etc.
I wonder what AWS will do if they have to make egress cheap! What is the next thing they can charge for that is actually cheap but people are happy to pay for.
> Workers can also send emails for free, and soon you will be able to process them as well with Email Workers.
There's got to be some limitations to that and I don't like it when they're not well defined. Looking at the MailChannels pricing, it looks like it's roughly 40x more expensive than AWS SES on the low end and 4x on the biggest plan before negotiating a custom deal.
I can send 500k emails and have a dedicated IP on SES for the same cost as 40k emails from MailChannels. Since their big value add seems to be scanning emails to prevent spam from user generated content, I just don't see it if that's not functionality you need because it's all wasted resources / unnecessary cost in those cases.
I assume there's a point where it's no longer free and I'm guessing the cost once you get there will be high.
Plus, am I sharing IPs with people who are sending such low-quality mail it requires outbound spam filtering? That seems like a huge negative on the deliverability side of things.
MailChannels is the service other services use, it's the de facto leader in combating spam. They are mostly meant to be used by high-volume hosted email services.
They are very good at detecting abuse. The leading cause of email deliverability problems is not advertisement, it's servers being hijacked by malicious actors.
[I work at Firebase]
Hi folks, I've seen some notable mentions of Firebase in this thread.
Last week, during the Firebase Summit we launched preview support for Web Frameworks like NextJS and Angular Universal: https://firebase.google.com/docs/hosting/frameworks-overview
Support during this early preview includes the following functionality:
- Deploy Web apps comprised of static web content
- Deploy Web apps that use pre-rendering / Static Site Generation (SSG)
- Deploy Web apps that use server-side Rendering (SSR)—full server rendering on demand
This page inspired me to actually convert as well. I have just recently been forced out of the AWS free tier and for some reason my insistence on using terraform and preserving a dynamic lockable state was somehow costing me $20 a month in DynamoDB costs.
Anyways, the pages import to take an existing git repository with a slew of CMS systems (mine being Hugo) supported, and the ability to just publish it to a custom domain in a series of clicks was actually really simple.
I think I dedicated 30 minutes of entire work and just saved ~$20/month because of it.
It uses clouflare workers, which is just spinning up v8 isolates, so there's no VM booting up. It's fast. They are also edge located. There are scenarios where using the kv or durable objects can cause a round trip back to the mothership, but not for reads.
> Durable Objects make this easy. Not only do they make it easy to assign a coordination point, but Cloudflare will automatically create the coordinator close to the users using it and migrate it as needed, minimizing latency.
It sounds magical. I would recommend trying it first... the experience of trying to actually build anything with it is quite un-magical. The documentation, CLI, workflow, and pricing (for sockets especially) all fall quite short.
I agree. I have learned as a general idea "use the fancy new thing if the pain of not using it is costing you a lot of money", because having your data nice and structured, typechecked in a relation DB with a query engine is the sweet spot for most applications. Firebase taught me this lesson. If you have an app with user ids and user profiles, and another records (plural) references them, you need a join, and non-relation databases suck at joining data.
Having data flung about the place in these objects sounds a bit scary (how do I back them up, and keep track of them, how do I join data from multiple objects, and what if those different objects are all around the world).
We're working on the documentation, I agree it can certainly be thin (or just not understandable). Please do file an issue for any improvements you'd like to see: https://github.com/cloudflare/cloudflare-docs/issues
Potentially stupid question: how is this different from hosting a static site on S3 and using CloudFront as a CDN? Assuming I don't need server-side JS, I don't see the benefit.
IMHO, when I use AWS I feel like I spend a lot of time dealing with the infrastructure. For example, you have to create the bucket, add IAM users that can deploy to it, set up CI that can do that deploy, configure CloudFront, etc..
With CloudFlare Pages you click a couple buttons in the UI and push to GitHub. When I tested it, I didn't get bogged down managing infrastructure which I've always struggled with (overthinking) in the past. I was almost instantly writing code that solves my problem(s).
The advantages aren't as huge with a purely static site, but they're still there IMO.
If you use a static site generator and it's in gitops, you can drop all of the considerations of AWS and focus on one control panel inside of Cloudflare and the content of your page. That's the benefit.
Having worked with some J2EE early in my career, I also had trouble mentally mapping "middleware" to an "interceptor" function when first encountering these "hip" frameworks
Cloudflare continues to add capabilities to their free tier to attract users. Meanwhile, Netlify just ejected all of the free plan users who work off GitHub.
One thing that stuck out was the comment about "Twitter cards", since Vercel/Next now has this built in: https://twitter.com/vercel/status/1579561293069316096