<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3" -->

---
title: the web server deployment model breaks at hobby scale
description: A developer narrates the compounding frustrations of building a web application intended for self-hosting at hobby scale. Each seemingly reasonable...
canonical: https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: the web server deployment model breaks at hobby scale | daily.dev
og:description: A developer narrates the compounding frustrations of building a web application intended for self-hosting at hobby scale. Each seemingly reasonable...
og:url: https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3
og:image: https://api.daily.dev/og/posts/f2VQ2XvO3.png
og:image:alt: the web server deployment model breaks at hobby scale
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# the web server deployment model breaks at hobby scale

**[Lobsters](https://daily.dev/sources/lobsters)** · 12 min read · 4 upvotes · 3 comments

## Summary

A developer narrates the compounding frustrations of building a web application intended for self-hosting at hobby scale. Each seemingly reasonable architectural decision — offloading static files to a reverse proxy, adding caching layers, splitting a JavaScript frontend from a non-JS backend, using a PostgreSQL extension for multilingual full-text search — creates new deployment burdens for end users. The post traces how each optimization that works cleanly in a professional environment (where you control the full stack) becomes a support nightmare when you can't assume what infrastructure admins have. The story ends with the developer bundling everything — reverse proxy, cache, Postgres with extensions, frontend, backend, and a process supervisor — into a single Docker container, effectively recreating the professional deployment model inside a container, just to restore the simplicity they originally wanted. The final image of a scraper triggering this entire chain of HTTP parsing for a two-year-old page underscores the absurdity.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://w.on-t.work/web-deployment-model>

## Questions this post answers

### why does postgres full-text search perform badly on japanese text

Postgres's built-in full-text-search functions rely on tokenization that breaks outside Latin script, making tsvector and GIN-index based search slow or ineffective for languages like Japanese. One workaround is pgroonga, a Postgres extension that adds proper full-text indexing support and works directly on existing table data without needing a separate document store like Elasticsearch, Meilisearch, or Sonic.

_daily.dev surfaces practical fixes like this for developers debugging multilingual search performance in postgres._

### why does caddy's built-in cache plugin sometimes corrupt responses

Caddy's caching plugin has been reported to corrupt responses under certain conditions because it is described as unbelievably mediocre in handling cache correctness, unlike a dedicated caching layer. Similarly, nginx's cache can get bogged down if admins forget to enable proxy_cache_lock, and Cloudflare users sometimes redundantly enable app-level caching on top of an edge cache, wasting memory.

_anyone tuning reverse proxy caching can track these gotchas via daily.dev before they hit production._

### why is it hard to deploy a server-side-rendered javascript frontend alongside a non-javascript backend

Every competent server-side-rendered single-page-app framework is written in javascript, so a backend written in another language cannot share a process with it. Embedding Node.js directly is fragile because Node is single-threaded and needs multiple load-balanced processes, and having the backend spawn Node processes itself means reimplementing a service manager like systemd or runit, so the practical solution is deploying the frontend as a fully separate application with its own reverse proxy rules.

_developers weighing frontend and backend deployment splits can follow these tradeoffs on daily.dev._

## Community take

How the wider developer community reacted, aggregated from 1 discussion and 26 comments across lobsters (as of 2026-09-14).

**TL;DR:** Commenters broadly sympathize with the deployment complexity problem but push back on whether the author's specific choices were necessary at hobby scale, with several arguing the added layers (reverse proxy, caching, SPA split, Postgres extensions) were self-inflicted rather than inherent to the model.

**Sentiment:** 20% positive · 50% mixed · 30% skeptical

**The case for**

- The Docker-everything conclusion is a pragmatic escape hatch that at least restores simplicity for end users.
- Old-school shared hosting (SFTP-to-webroot LAMP style) still works well for simple personal sites and avoids most of these problems.
- Rejecting or trimming unused query parameters is a legitimate technique to reduce unnecessary processing.

**The pushback**

- Many of the architectural choices criticized — reverse proxy, caching layer, SPA split, Postgres extensions — are arguably unnecessary at true hobby scale and were self-imposed.
- Shipping everything in a single Docker container creates its own problems: no security update cadence, poor backup story, and opaque internals when things break.
- The post's definition of 'hobby scale' seems to assume a level of complexity that many hobbyists would never reach or need.
- Bundling a full Postgres instance inside a container conflicts with self-hosters who already have centralized database setups with proper backup tooling.

**By community**

- lobsters (mixed): Commenters are split between sympathy for the deployment pain and skepticism that the author's choices were actually necessary, with pointed criticism of the Docker-container conclusion creating its own maintenance and backup burdens.

**Hottest debate:** Whether the complexity described is an inherent flaw in the web deployment model or simply the result of unnecessary architectural choices the author made voluntarily.

**Open questions**

- Is there a deployment model that gives self-hosters simplicity without forcing the app author to bundle everything into a single opaque container?
- How should hobby-scale apps handle security updates and backups when shipped as a monolithic Docker image?
- Could SQLite plus a single compiled binary eliminate most of these layers without sacrificing functionality?

**Highlights**

> This article and I have a very different idea of what "hobby scale" means.
> — [bakkot on lobsters · 13 points](https://lobste.rs/s/rn4inr/web_server_deployment_model_breaks_at#c_kwaozm)

> This misses the final steps! An app is shipped only as a docker container, but it never gets rebuilt for security updates for packages inside the docker container - only when a new app update is released. An app is shipped only as a docker container, making backup harder - as a self hoster, my central Postgres setup etc already has barman. Doing new backup setups for Postgres or MySQL in docker is unfun. If the author uses some random nosql DB I am not familiar with, it’s even more unfun. No hobby docker setups that I have ever seen document anything around backup & recovery. Then some part of the deployment breaks in a way the original author didn’t anticipate (eg I had this last night where Nextcloud AIO’s backup process stopped working). So now, I get the fun of wading into their docker setup to try to figure out what broke and how to fix it, wasting more time than setting up hosting by hand would have done.
> — [fourfourthree on lobsters · 5 points, 1 comments](https://lobste.rs/s/rn4inr/web_server_deployment_model_breaks_at#c_crnx5y)

> The thing is that this example added a lot of unnessecary cruft as "necessary". You don't need reverse proxies, dedicated static file hosting, built-in certificate renewal, or caching at the hobby scale.
> — [JulianSildenLanglo on lobsters · 2 points, 1 comments](https://lobste.rs/s/rn4inr/web_server_deployment_model_breaks_at#c_es5r6m)

> Here's what I think my ideal stack would look like for a greenfield web app project: * Database in SQLite. For self-hosted apps at small to medium scale, SQLite is more than good enough. * App server written in Rust, designed to run behind a reverse proxy so you can manage your TLS cert using whatever you're already running. * Static assets baked into the Rust binary. No need to even `open` them, let alone `read` or explicit `mmap`; they're just there in virtual memory, and the OS can demand-page them in if needed. * No caching layer. With efficient native code, computing both unauthenticated and common authenticated responses should just be fast enough. * Front-end in [Marko 6](https://markojs.com/). Multi-page application built around server-side rendering, with minimal client-side JS (built on fine-grained, compiler-based reactivity) for the things that actually need it. Marko at least theoretically supports server-side adapters other than Node, so should be able to embed V8 in the Rust app server. I think this is the most speculative part. The result is a single binary that one can run behind a reverse proxy with a very simple Caddy or nginx configuration.
> — [mwcampbell on lobsters · 1 points, 1 comments](https://lobste.rs/s/rn4inr/web_server_deployment_model_breaks_at#c_mqgmqv)

**Source threads**

- [lobsters](https://lobste.rs/s/rn4inr/web_server_deployment_model_breaks_at) · 30 points · 26 comments

## Community discussion

Top comments from developers on daily.dev.

**@agustinbarrientos** · 1 upvotes

> One boring container starts sounding pretty luxurious after the fifth optional piece of infrastructure.

**@jhon3484** · 0 upvotes

> **What lands**
>
> The central insight is genuinely good and underarticulated: _architectural complexity is not free, and the bill is paid by whoever deploys it._ Most performance writing treats the deployment target as a constant. Framing each optimization as a transfer of cost from the developer's machine to a stranger's server is the right lens, and the escalating structure — each fix reasonable in isolation, the aggregate absurd — earns the conclusion instead of asserting it.
>
> The ending is the strongest part. Recreating a full production stack inside one container to restore single-binary...

**@trevorsuna** · 0 upvotes

> That single-container ending is funny because it is also understandable: the deployment boundary becomes the product. The tradeoff is making backups and upgrades explicit, but for hobby self-hosting, one boring artifact can be kinder than asking users to assemble a miniature platform team.

## Similar posts on daily.dev

- [I stopped installing every new self-hosted app, and my local stack instantly got healthier](https://daily.dev/posts/i-stopped-installing-every-new-self-hosted-app-and-my-local-stack-instantly-got-healthier-oswkkbsp0) · XDA Developers · 4 upvotes · 0 comments
- [When Reverse Proxies Surprise You: Hard Lessons from Operating at Scale](https://daily.dev/posts/when-reverse-proxies-surprise-you-hard-lessons-from-operating-at-scale-fgvbclqmo) · InfoQ · 0 upvotes · 0 comments
- [The Heroku Nostalgia Trap: Why Easy Deploys Aren't the Only Answer](https://daily.dev/posts/the-heroku-nostalgia-trap-why-easy-deploys-aren-t-the-only-answer-i4xf1g7s7) · freeCodeCamp · 2 upvotes · 0 comments
- [JS-heavy approaches are not compatible with long-term performance goals](https://daily.dev/posts/js-heavy-approaches-are-not-compatible-with-long-term-performance-goals-g7unzk9jj) · Hacker News · 0 upvotes · 0 comments

---

Tags: [#cicd](https://daily.dev/tags/cicd), [#self-hosting](https://daily.dev/tags/self-hosting)

[View this post on daily.dev](https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"the web server deployment model breaks at hobby scale","url":"https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3"},"datePublished":"2026-08-07T13:10:47.684Z","dateModified":"2026-09-14T06:53:14.725Z","description":"A developer narrates the compounding frustrations of building a web application intended for self-hosting at hobby scale. Each seemingly reasonable...","image":"https://media.daily.dev/image/upload/s--58gMhC4P--/f_auto/v1722860399/public/Placeholder%2012","thumbnailUrl":"https://media.daily.dev/image/upload/s--58gMhC4P--/f_auto/v1722860399/public/Placeholder%2012","isAccessibleForFree":true,"articleSection":"Lobsters","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Lobsters","logo":"https://media.daily.dev/image/upload/s--tl8v_Fku--/f_auto,t_logo/v1698841318/logos/lobste.jpg","url":"https://daily.dev/sources/lobsters"},"commentCount":3,"discussionUrl":"https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":4},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":3}],"keywords":"cicd,self-hosting","timeRequired":"PT12M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Lobsters","item":"https://daily.dev/sources/lobsters"},{"@type":"ListItem","position":3,"name":"the web server deployment model breaks at hobby scale"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3","comment":[{"@type":"Comment","text":"One boring container starts sounding pretty luxurious after the fifth optional piece of infrastructure.","datePublished":"2026-08-08T17:31:24.271Z","url":"https://daily.dev/posts/f2VQ2XvO3#c-G8c700CKp","author":{"@type":"Person","name":"Agustin Barrientos","url":"https://daily.dev/agustinbarrientos","image":"https://media.daily.dev/image/upload/s--5ayxQnqn--/f_auto/v1788281802/avatars/avatar_wQYYVe5Tbj0NJ7C7qPoa8?_a=BAMAMicg0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1}},{"@type":"Comment","text":"What lands\nThe central insight is genuinely good and underarticulated: architectural complexity is not free, and the bill is paid by whoever deploys it. Most performance writing treats the deployment target as a constant. Framing each optimization as a transfer of cost from the developer’s machine to a stranger’s server is the right lens, and the escalating structure — each fix reasonable in isolation, the aggregate absurd — earns the conclusion instead of asserting it.\nThe ending is the strongest part. Recreating a full production stack inside one container to restore single-binary simplicity is a real, funny, slightly damning image. The scraper hitting a two-year-old page through seven layers is a good closer because it makes the point about amortization: all that machinery exists to serve traffic patterns that hobby deployments don’t have.\nWhere it’s thin\n\nIt never separates “complexity for performance” from “complexity for correctness.” These have very different justifications. A reverse proxy for static files is pure throughput optimization at hobby scale — genuinely unnecessary. But a Postgres extension for multilingual full-text search is a feature, not an optimization; the alternative isn’t “simpler,” it’s “search that doesn’t work for half your users.” Lumping them together weakens the argument, because a reader can dismiss the whole thing by pointing at the one item that was never optional.\nThe container isn’t actually the failure the post implies. Bundling supervisor + proxy + cache + DB into one image is presented as ironic defeat, but it’s a legitimate and common pattern for self-hosted software — it’s how you ship an appliance. The real cost is specific and worth naming: no independent scaling, a supervisor as PID 1 with signal-handling and zombie-reaping caveats, docker restart as the only remediation, data-in-image mistakes, and upgrade paths that now include a Postgres major-version bump the operator didn’t ask for. Those are the honest downsides, and the post gestures at absurdity instead of listing them.\nThe road not taken goes unexamined. The counterfactual — SQLite with FTS5, server-rendered HTML, static files served by the app itself, no cache layer — is the actual alternative, and it deserves a paragraph. Not because it’s always right, but because “what would this have cost me in features and ceiling?” is the question the post raises and doesn’t answer. Right now it reads as I regret my choices; it would be stronger as here is the tradeoff curve, and here’s where I’d sit on it next time.\n“Non-JS backend” is doing unexamined work. The frontend/backend split is framed as a deployment problem, but it’s mostly a build problem — a build step, a second toolchain, asset versioning, CSP. Those are real and separable from deployment. Worth being precise about which burden fell where.\n\nOne structural suggestion\nThe post is a narrative of accumulation with no framework to hand the reader. A short closing rubric would make it durable and quotable rather than just relatable — something like: does this component need independent configuration, does it hold state, does it need to survive a restart, and can a non-expert diagnose it when it breaks? Anything that fails those tests is a component you should own inside your process, not delegate to the operator’s infrastructure. Readers will forget the anecdote; they’ll reuse the rubric.\nTone note\nThe self-deprecation is charming but slightly overcorrects. The developer built a working, self-hostable, multilingual, cached application — the container is the punchline, not the tragedy. Landing on “this is the correct amount of complexity for what I wanted, and here’s what it cost” would be a more useful ending than “look what I’ve become.”","datePublished":"2026-08-08T02:09:22.551Z","url":"https://daily.dev/posts/f2VQ2XvO3#c-psz1gkNQA","author":{"@type":"Person","name":"jhon34","url":"https://daily.dev/jhon3484"}},{"@type":"Comment","text":"That single-container ending is funny because it is also understandable: the deployment boundary becomes the product. The tradeoff is making backups and upgrades explicit, but for hobby self-hosting, one boring artifact can be kinder than asking users to assemble a miniature platform team.","datePublished":"2026-08-08T04:39:41.397Z","url":"https://daily.dev/posts/f2VQ2XvO3#c-BgtI74xCk","author":{"@type":"Person","name":"Trevor Suna","url":"https://daily.dev/trevorsuna","image":"https://media.daily.dev/image/upload/s--dZ7gXxpp--/f_auto/v1784081551/avatars/avatar_EMoP47rpuw8DNjhp6R1b6?_a=BAMAMicg0"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/the-web-server-deployment-model-breaks-at-hobby-scale-f2vq2xvo3#faq","mainEntity":[{"@type":"Question","name":"why does postgres full-text search perform badly on japanese text","acceptedAnswer":{"@type":"Answer","text":"Postgres's built-in full-text-search functions rely on tokenization that breaks outside Latin script, making tsvector and GIN-index based search slow or ineffective for languages like Japanese. One workaround is pgroonga, a Postgres extension that adds proper full-text indexing support and works directly on existing table data without needing a separate document store like Elasticsearch, Meilisearch, or Sonic. daily.dev surfaces practical fixes like this for developers debugging multilingual search performance in postgres."}},{"@type":"Question","name":"why does caddy's built-in cache plugin sometimes corrupt responses","acceptedAnswer":{"@type":"Answer","text":"Caddy's caching plugin has been reported to corrupt responses under certain conditions because it is described as unbelievably mediocre in handling cache correctness, unlike a dedicated caching layer. Similarly, nginx's cache can get bogged down if admins forget to enable proxy_cache_lock, and Cloudflare users sometimes redundantly enable app-level caching on top of an edge cache, wasting memory. anyone tuning reverse proxy caching can track these gotchas via daily.dev before they hit production."}},{"@type":"Question","name":"why is it hard to deploy a server-side-rendered javascript frontend alongside a non-javascript backend","acceptedAnswer":{"@type":"Answer","text":"Every competent server-side-rendered single-page-app framework is written in javascript, so a backend written in another language cannot share a process with it. Embedding Node.js directly is fragile because Node is single-threaded and needs multiple load-balanced processes, and having the backend spawn Node processes itself means reimplementing a service manager like systemd or runit, so the practical solution is deploying the frontend as a fully separate application with its own reverse proxy rules. developers weighing frontend and backend deployment splits can follow these tradeoffs on daily.dev."}}]}
```

