Hacker News new | ask | show | jobs
by eric4smith 1293 days ago
Slightly off topic...

Back before my Phoenix/Elixir days, we used to have to cache almost everything. Now we don't cache anything -- even with more traffic and less servers. Now, the projects I work on are not getting millions of views every day. But they are still important for many customers.

We don't really design anything that needs to be cached anymore. Just better access patterns and table design as we get wiser.

Take Wordpress as an example. There really should not be a need to cache a Wordpress site. But some of the most popular plugins are those that cache. To be fair, I suppose, their legacy non-optimal database design access pattern and code is responsible for this.

Just getting something up and aiming for product-market fit is priority #1 and then struggling with caching if it gets popular, at which point, more resources can be thrown at it.

11 comments

Elixir is not some golden ticket and in my experience still needed caching (ets and/or redis). I worked on an elixir service that topped out at around 2k requests per second with 5 servers even with some caching of the high-read/low-write flows. This was mostly limited by db cpu pressure against postgres with lots of materialized views and monstrous queries being inefficient due to over normalization and, maybe, partly affected by uuid primary keys.

I came to this system with prior experience using Go and mysql where I expected base performance of 1-5k queries per second per node before any optimizations like (non cpu) caching but also didn't use triggers or anything fancy to prevent db cpu pressure.

I got a bit rambling and perhaps a bit off topic, but elixir is not something that side steps the need for a cache when your db is maxed out.

2000 requests per second implies your system was badly designed. If you’re saying it was mostly database bottlenecks why would that not affect the Go version in the same way?
The point I attempted to make was that elixir and your caching needs are orthogonal.

However, to indulge Go vs Elixir in this context (note it was two different systems, companies, and scale referenced above): Elixir has the amazing Ecto query builder and I think poor schema design along with good tooling let folks be productive and build a couple of years of cruft into a tangled knot of table dependencies and access patterns and materialized views.

Go tends to eschew ORM like things and I believe some pressure on the devs to think more about the actual queries being (hand) generated would have exposed schema inefficiencies earlier (instead of Ecto automagically pulling all the data you need, you see the heavy lifting when writing the queries).

And to your point, with a fucked schema and or access patterns, Go vs Elixir or any other language is a moot point. Cheers!

Of course you can use an ORM with Golang, and will have reduced throughput. However, I wonder how much you can profile for both languages and fix the bottlenecks by rewriting things. It can also depend on the machine and how the VM allocates the threads and memory allocation (for example multi chiplet, multi rambank support).
Ecto isn’t an ORM it’s two things 1) an Elixir DSL for building SQL Queries 2) Ecto.Changeset a system for validating and managing data changes before they go into your database.

I think bad database design can happen anywhere and good database design can happen in a PHP application. It’s not necessarily language dependent and always refactoring technical debt on the database design can be some of the most productive changes you can make to a service.

> Take Wordpress as an example. There really should not be a need to cache a Wordpress site. But some of the most popular plugins are those that cache.

Caching gives sites about two orders of magnitude speed uplift in my experience. Sometimes more. Especially if you are building the pages live and compressing them.

Brotli -11 is really really expensive and egress data transfer is one of the more expensive commodities to purchase from cloud venders.

Caching also reduces latency significantly - which is a much better user experience.

>Take Wordpress as an example. There really should not be a need to cache a Wordpress site. But some of the most popular plugins are those that cache. To be fair, I suppose, their legacy non-optimal database design access pattern and code is responsible for this.

To anyone reading this, do not assume that you don't need to cache your Wordpress site! I remember running a test on my site once (basic WooCommerce site running on a DigitalOcean VPS), and simply turning on the free version of WP Fastest Cache was the difference between serving 30 users/min and crashing vs. serving 1000. Drastically lowered page load times too.

In my experience, the caching of WordPress became essential on shared hosting which one of my clients was somewhat bound to for....reasons. Without, each page load was atrociously slow, but once enabled and the cached was warmed, the site moved as quickly as anywhere else.

It's interesting because a custom legacy PHP application on the same shared host didn't demonstrate such slowness, but I did write some aggressive in-request caching (static variables for repeatedly called functions, mainly) to great performance effect.

Just throwing more ressources at it will make your hosting company happy. I am working for one, so I will not disagree with you. If I were to mention its name, I would though, since a lot of what we do is help our clients to make their webapplications run more efficently (and thus saving them a lot of money in the long run).
WordPress by itself isn’t so bad. It’s the plugin/theme developers who likely have no idea what they’re doing or why what they’re doing is bad.
My client is running 21 plugins :(
At Automattic, I think the mu-plugins folder for WordPress.com had at least a hundred directories and at least another count's worth of the same in files. It was massive.
Keeping operating modes simple is something that pays off especially in large scale systems (let alone smaller ones): https://archive.is/2S2ME (Doing Constant Work, Colm MacCárthaigh, AWS Builders' Library).

Generally, I've found that, in the guise of doing the simplest thing, I've done the most naive-est thing possible, which unfortunately comes with the burden of tech debt. So, as a rule of thumb, given the small tech shop we are, I tend to favour systems that are fully-managed or serverless and prefer to take on whatever tech debt using it throws at me.

WP cache is "necessary" if you run on a low-end shared host, where contention for resources, context switching, and basically any dynamic feature of the site gets too slow in a big traffic surge.
1M views per day is only ~12 views per second. It should be possible to easily run at least 1K DB queries per second. Based on this, it seems that you would have quiet a bit of room with a non-cached model. Of course, peak traffic estimates are really the key.

I don't understand how Phoenix/Elixir impacts this however.

Phoenix / Elixir (really, BEAM) enforce a worldview that results in non-bottlenecking code. You can do this yourself with a certain amount of disclipine in other languages. You should do this yourself if you are getting millions (or billions, etc...) of hits per second to gain access to system with a lower constant than BEAM. This is why Discord (for example) shifted to Rust.

Two interesting things are true:

1. Engineers have through lack of experience (or care) bottlenecked systems that had 12 views per day. Guardrails are useful particularly if there are shared resources or bottlenecks can impact busier neighbors.

2. The threshold where a shift out of Elixir is a good idea climbs at the same rate as Moore's law. Discord made their Elixir->Rust moves a lot later than Twitter made Ruby->Java ones.

Bottlenecked by what? Cache misses? IO?
Aren't you just pushing down the caching from HTML and App layers to DB layers, OS layers, Disk layers and CPU caches layers?

Something needs to be cached always, so the DB and Disk need at least cache blocks.

If your main page is put together by running a bunch of queries it’s just a waste of resources to run these for every bot hit.
I believe in caching where it makes sense. This is usually app and implementation specific. But I do agree that a cache shouldn't make up for bad DB design and tuning.