News for hackers. Stuff that matters.
Re:Single dependency stacks by theptip on Wednesday February 09, 2022 @01:19PM (#30276112)
I'm a big fan of this approach, having built a Django monolith with the standard Celery/RMQ, dabbled in Redis for latency-sensitive things like session caching, and never hitting scale where any of those specialized tools were actually required (despite generating substantial revenue with the company).

One thing to note, if you use pq or another Postgres-as-queue approach, you should be aware of the work you'll need to do to move off it -- this pattern lets you do exactly-once processing by consuming your tasks in the same DB transaction where you process the side-effects. In general when using a separate task queue (RMQ, SQS, etc.) you need to do idempotent processing (at least once message semantics). A possible exception is if you use Kafka and use transactional event processing, but it's not serializable isolation.

This is probably a reason in favor of using a Postgres task queue initially since exactly-once is way simpler to build, but just be aware that you're going to need to rethink some of your architectural foundation if/when you need to move to a higher-throughput queue implementation.

Re:Single dependency stacks by samwillis on Wednesday February 09, 2022 @01:34PM (#30276408)
Your whole first paragraph literally describes our situation exactly, same stack and all. Classic premature optimisation.

It’s made it so clear to me that so much of what you read on HN about the latest and greatest scaling tricks are only relative to a tiny tiny fraction of business.

Re:Single dependency stacks by jrumbut on Wednesday February 09, 2022 @03:09PM (#30277762)
Getting good at solving problems with relational databases is a highly underrated skill.

They are really underutilized by many projects.

Not to say any other software is bad, just that keeping the stack simple can help small teams move quickly and not get bogged down fighting fires. Also, the paths to scale up the major RDBMSes are well documented and understood. With a newer service and many interacting systems in your back end you end up having to be a pioneer (which takes time away from implementing new features).

Re:Single dependency stacks by jaxrtech on Wednesday February 09, 2022 @03:42PM (#30278205)
Absolutely. I've also seen my fair share of horrendous home-grown "ETL" programs that waste more time shuffling bytes to and from database with poor ORM queries in loops, that could be done with a couple half decent SQL queries.

Probably the most useful things for me was learning relational algebra in college, and having been thrown on the deep end on a team that was very SQL heavy (not withstanding attempting to debug Oracle PL/SQL syntax errors while pulling your hair out about a missing closing parenthesis -- of which isn't the problem).

The usual challenge seems to be fetching data from external services or performing complex business that may conditionally load things -- things that can be awkward in procedural SQL. At the end of the day, you're building a messy ad-hoc dependency graph that is being manually executed very inefficiently. Would be better to just have your code just describe the dependency graph and treat each value transparently as a promise/future and then have a separate engine execute it.

Anyhow, something something monads with lipstick, I digress...

Re:Single dependency stacks by KptMarchewa on Wednesday February 09, 2022 @03:53PM (#30278328)
ETL using ORM? Really?
Re:Single dependency stacks by PeterisP on Thursday February 10, 2022 @11:12AM (#30288261)
Actual ETL systems would not, however, if you have a homegrown pile of scripts fulfilling the ETL role, I would not be surprised if those scripts would use ORM.
Re:Single dependency stacks by SteadBytes on Thursday February 10, 2022 @12:21PM (#30289435)
Agreed. Are there any resources you recommend for getting good at solving problems with relational databases?
Re:Single dependency stacks by jjice on Wednesday February 09, 2022 @02:35PM (#30277320)
FWIW, setting up a Redis server and setting up some basic caching middleware is pretty straightforward in my experience. Did this at my job a month ago in an afternoon.

I'd say the biggest overhead is adding Redis if you don't already have it, and that addition's difficulty will vary based on how you host Redis. We use Elasticache on AWS, so just a few clicks and set it in the same VPC.

I guess the real question comes down to how you feel about an extra moving part. Redis is probably the part of our system that has had the least hiccups (very much set and forget and no resource issues so far), but I can understand in the case where you'd rather not add more than a DB.

I'd say it's just as easy to setup as Postgres. Elastic search I hear is a pain, though I have no personal experience.

Re:Single dependency stacks by blowski on Wednesday February 09, 2022 @03:38PM (#30278166)
The pain is not initially setting it up, it’s in the ongoing maintenance. Redis is one of the less painful services to support, especially if using a managed version. But I don’t like the trend of defaulting to using Redis without really justifying it.
Re:Single dependency stacks by jjice on Wednesday February 09, 2022 @03:45PM (#30278237)
You're right for sure if the service is small - Redis would be overkill. I guess I'm coming at it from the perspective I'm most used to where we use it for data caching and session data since we have multiple servers, so handling it any other way would be more work.
Re:Single dependency stacks by lmm on Wednesday February 09, 2022 @09:43PM (#30281835)
Redis is a better default-without-thinking than Postgres IMO. Transactions and referential integrity make some big tradeoffs and it's easy to accidentally rely on them without thinking through the consequences. Global serializability is theoretically even worse, but the direct analogy with application-layer threading makes it easier to understand and avoid the pitfalls.
Re:Single dependency stacks by naasking on Wednesday February 09, 2022 @11:16PM (#30282395)
Funny, I think the exact opposite is the case. It's rare that an application needs more throughput than Postgres on modern hardware can provide. Unless you know you actually need that throughput, you're better off defaulting to Postgres and enjoy that referential integrity.
Re:Single dependency stacks by lmm on Thursday February 10, 2022 @01:24AM (#30283009)
> It's rare that an application needs more throughput than Postgres on modern hardware can provide.

Agreed, but it's extremely common to need more resilience and/or better multi-DC support than Postgres can provide, and if you've implicitly built your datamodel on Postgres' guarantees then you might find it very hard to migrate to something more distributable. Frankly true master-master HA should have been table stakes for any serious datastore for at least the past decade, as soon as it became clear that cloud was a thing or even before that. (Redis also falls down on that front in terms of what it offers itself, but it's much easier to migrate to something more distributable, IME).

Re:Single dependency stacks by smoe on Wednesday February 09, 2022 @04:35PM (#30278869)
From my view, the issue in the case is not how difficult it is to setup Redis for caching (it is indeed just a couple of clicks/commands), but the new issues one has to deal with when resorting to caching things too prematurely, instead of making the app fast enough with minimal effort.
Re:Single dependency stacks by barrkel on Wednesday February 09, 2022 @04:34PM (#30278850)
Setting up caching usually isn't the problem, it's invalidation and eviction that bites you.
Re:Single dependency stacks by btown on Wednesday February 09, 2022 @01:48PM (#30276649)
https://www.2ndquadrant.com/en/blog/what-is-select-skip-lock... describes the benefits of the above approach.

Something to bear in mind is that if you have a bug or crash in your task handler that causes a rollback, another worker will likely try to grab the same task again, and you might end up clogging all of your workers trying the same failed tasks over and over again. We use a hybrid approach where a worker takes responsibility for a task atomically using SKIP LOCKED and setting a work-in-progress flag, but actually does the bulk of the work outside of a transaction; you can then run arbitrary cleanup code periodically for things that were set as work-in-progress but abandoned, perhaps putting them into lower-priority queues or tracking how many failures were seen in a row.

Postgres is absolutely incredible. If you are at anything less than unicorn scale, outside of analytics where columnar stores are better (though Citus apparently now has a solution for this - https://www.citusdata.com/blog/2021/03/06/citus-10-columnar-...), and highly customizable full-text search (it's hard to beat Elastic/Lucene's bitmap handling), there are very few things that other databases can do better if you have the right indices, tuning, and read replicas on your Postgres database.

Re:Single dependency stacks by smoe on Wednesday February 09, 2022 @04:27PM (#30278740)
> just be aware that you're going to need to rethink some of your architectural foundation if/when you need to move to a higher-throughput queue implementation

I haven't seen many if any projects that didn't require some architectural rethinking over their lifetime. I have seen more, that where arguably over engineered in the beginning, but then never lived long enough to actually benefit from it.

Not saying everyone should use Postgres-as-queue for every project. But for a lot of projects it is going to be much harder to acquire the active user base generating the throughput Postgres can't handle, than doing continuous refactoring of the system to deal with the changing requirements.

Re:Single dependency stacks by closeparen on Wednesday February 09, 2022 @03:09PM (#30277767)
Dependencies are not equal in this regard. For example in a corporate context, we have basically 1.5 people in Eastern Europe maintaining Redis for 5,000 engineers. Kafka is more like 15.
Re:Single dependency stacks by rattray on Wednesday February 09, 2022 @02:09PM (#30276977)
For Node folks interested in a postgres-based task queue, I find graphile-worker[1] to be pretty terrific. Docs make it sounds like it's only for postgraphile/postgrest but it's great with any Node app IMO.

[1] https://www.npmjs.com/package/graphile-worker