I think that's the key. Most of us aren't Google/Facebook/whatever. Yet lots of people want to mimic those. A simple stack with a relation database on a single machine still goes a long way. In fact, it goes a lot longer way today than it did 20 years ago. It's ok to scale when you need to, but I think premature scaling is the wrong way to go, especially since most things never get to FB/Google/etc size.
Every time this argument pops up, I end up wondering if it’s really about architectural complexity, or if it’s about sticking with the old and known.
Now to try and answer your question, I think a relational database is a lot more complex than a simple key value store, but if it's a good implementation, it will hide this complexity from the user, and using the database will be rather simple. It can be as simple as a key value store since you can just use a relational database like one. Note that this hiding of complexity is by design, it is one of the main goals of the relational model, it's not accidental.
Example Go's mgo driver by Gustavo Niemeyer was simple and effective, but abandoned. The official drivers is unnecessarily complicated. And Go's need to have "context" everywhere adds to this, but MongoDB is not complex. Idk I'm not some super genius and picking up MongoDB was really easy. Querying (aka aggregation pipelines), you have to think of that as "pipes in bash". It's in the words aggregation pipelines. find | groupby | sort | filter | select. Something like that. It's not SQL it's different, but not complex, sorry.
Like, if you were never exposed to rxjs and are now trying to build things with it doing
$stream.pipe(
switchmap(),
filter(),
etc(),
)
It does seem more complex than stream.map().filter().etc()
but it's only so because you haven't put in the effort to learn that way.Now write DBA scale ISO SQL 2016 / Transact SQL / PL/SQL in that interesting Mongo flavoured language, including database engine debugger integration, and JIT compilation.
a raspberry pi can pretty much serve 100k req. / second. An average dev laptop should be able to handle 1M req. / second without much issues
Depends on what you do. It's quite easy to hit these numbers with a low number of static pages, but apps that can easily work with static pages usually don't have DevOps people. That's why I went with thousands, to have a reasonable number for an app that actually does some complex processing.
I appreciate the sentiment, but my intuition says that number is too high. What would that look like? I can't picture nginx or haproxy serving up a static 'hello world' response at that volume on a Pi3.
And if you do anything with a slow-ish 3rd party API you're probably going to hit the TCP socket limit before you can respond to 100k/s.
Legitimately curious about whether my intuition is wrong. I don't have an unused Pi handy to test it myself.
Edit: It's possible you're citing https://levelup.gitconnected.com/serving-100k-requests-secon... ? Pretty interesting article in any case, especially this claim:
> This test pitted a native C++ server against a scripted Node.js one, so of course the outcome was given. Well, not really. If I run the same test using µWebSockets.js for Node.js, the numbers are a stable 75k req/sec (for cleartext). That’s still 8.5x that of Node.js with Fastify and just shy of 75% of µWebSockets itself.
Edit 2: Doing a bit more research and finding some other benchmarks online, it seems like 100k with µWebSockets is plausible. I recant my skepticism.
I'm not sure you have much experience working on websites. Multiple deployments are required for performance reasons, which is the main driving force for paying hefty bills for CDNs, and their recent investment in edge computing.
You deploy to multiple deployments in multiple regions in a good part to drive down those 300ms requests to sub 50ms. Otherwise your user gets fed up and drops you in favor of a competitor.
But if you work on a service who has only a dozen users in the same region and can wait in turns to see who can make a request, go right ahead with your production raspberry pi setup.
one raspberry pi per continent :p
e.g. I'm in a small rural village in southern france right now and I get 2GB down / 1GB up more or less with a 9ms speedtest ping (which is slow, it's often 2ms) - anyone from europe would get < 50ms ping notwithstanding the latency between them and their isp
by the time my website has, say, > 500k req/second I can definitely invest in, idk, some used 2015 i7 laptop to give myself a x10. For reference, 1M requests per second is Instagram in 2015, one of the most used websites in the world - by the time you're at that scale you've been bought by Facebook anyways.
I bought artisanal knitted socks for Christmas. If their website is faster than their knitting that’s good enough. That website is part of the 99%.
I ultimately agree with you, but in between a raspberry pi and “hefty bills CDNs” is something like a half rack at a Colo, a f5, and a couple PowerEdges.
(Half kidding)
Not every page loads 50 different resources. Not every page serves people globally. Not every page has competitors.
I might say the same about you. Be respectful.
How big are these requests? If you're returning more than 1kB including all the headers, you're not beating 100kreq/s on a standard consumer-level 1Gbit link.
It wouldn't be possible to get that request rate outside of a microbenchmark, just because of the network speed the pi supports.
- 2.5G: https://www.jeffgeerling.com/blog/2020/testing-25-gbps-ether...
- 10G (in practice 3.6G max which is more than what most can expect from their ISP): https://www.hackster.io/news/10-gbps-ethernet-on-a-raspberry...
At my current company we're at cusp when we need to address scalability to able to grow as a business, and the business is growing. It took several years to get to this point, but here we are.
I prefer simplicity as much as the next guy, but at some moment it becomes simpler overall to use cloud services controlled by k8s than to maintain large amounts Ansible scripts and Jenkins jobs.
With that, by the way, comes an inevitable untangling of various parts in the software, and simplification of it. To be fast you need the processing path to be simple.
What functionality? Automated unit tests to ensure you're not shipping code that is so broken that it even breaks basic invariants? Automated integration tests that ensure you're not shipping code that fails to call other components/services? UI tests to ensure that your latest commit didn't made your prod service unusable for the end user? Performance tests that help you determine if your latest change doesn't suddenly exhaust your computational resources in peak demand?
People are always suprised when they see a minimal webserver instance on a ten year old debian [0] handling tens of thousands of requests, without issue. It might go down once a decade because the disk failed, but it cost 1200$ to run over that decade. I don't think that's the perfect way, but modern infrastructures love to include a lot of complexity when it's not needed. The problem is that including something is very easy and the cost is only payed once it breaks. Also, hardware is really cheap (you might not think so, but if you compare it to western IT salaries, it is).
[0] I know outdated instances with no update strategy are not really a benchmark, but I encourage you to go out and ask people what their container base image upgrade strategy is - the situation really did not change that much.