One thing that jumps out at me is that it seems they didn't use any Postgres connection pooling. They mention that going above 100 concurrent connection would bump them into a more expensive Postgres plan, which really only makes sense if you don't use a pool.
My first instinct is that the number of requests seems really low, but I have no idea about the complexity of each request. To me that is kind of a crucial information to actually evaluate anything in the blog post.
This is a great point. One of the ideas we were wanting to get across is that using a very simple tech stack you can get to a number of requests that most services will never meaningfully see. We do have our Django configured to pool connections, but it's configured per process, and not sharing them across all the various web processes that we're running: https://docs.djangoproject.com/en/3.2/ref/databases/#persist...
I'd be curious to see if there is a meaningful gain from that approach, if anyone has done the transition before.
That's one part where having multiple completely independent processes is a disadvantage to just having threads. I never benchmarked this, but I always heard that Postgres processes are expensive and you should always use a connection pool. But this is probably more noticeable on the DB server side, where each process uses memory. I never used it myself, but PG bouncer might be useful to you in this case.
The number of requests still feels slow, and it isn't clear to me from the blog post whether that is DB limited or CPU limited on the application servers. Even with writes on each access Postgres should still be bored at that kind of load.
Yea, our IO and CPU of our Postgres instance is around 20% currently. We haven't hit too many issues with Postgres, so haven't delved too deeply into the performance.
I think people seeing performance posts are used to people pushing huge numbers. Our intent here was to show that using standard off the shelf tools with a tiny bit of architecting, you can hit huge performance numbers at a reasonable cost. We have lots of various ways to shave performance, but we're pretty sure we could scale 2-3x with the same stack without a ton of work.
Postgres is mostly bored (CPU sub 20% utilized) with 60 write requests per second which is normal peak traffic. Even traffic spikes to 100-120 don't usually change that much.
As our ad network grows though, everything has to grow pretty linearly (writes, reads, requests, etc.) and I hope our approach will continue to work well even with double or triple these numbers.
I don't think they need 100 more current connection. Assume one process take 1 connection, only several connection are required.
I think there must be some misconfiguration there. otherwise, the throughout should not be that low.
If possible, the author should setup a demo (contrived query, but similar to production scenario). From there, others can give valid suggestion or improve the code and configure.
Comments
One thing that jumps out at me is that it seems they didn't use any Postgres connection pooling. They mention that going above 100 concurrent connection would bump them into a more expensive Postgres plan, which really only makes sense if you don't use a pool.
My first instinct is that the number of requests seems really low, but I have no idea about the complexity of each request. To me that is kind of a crucial information to actually evaluate anything in the blog post.
This is a great point. One of the ideas we were wanting to get across is that using a very simple tech stack you can get to a number of requests that most services will never meaningfully see. We do have our Django configured to pool connections, but it's configured per process, and not sharing them across all the various web processes that we're running: https://docs.djangoproject.com/en/3.2/ref/databases/#persist...
I'd be curious to see if there is a meaningful gain from that approach, if anyone has done the transition before.
That's one part where having multiple completely independent processes is a disadvantage to just having threads. I never benchmarked this, but I always heard that Postgres processes are expensive and you should always use a connection pool. But this is probably more noticeable on the DB server side, where each process uses memory. I never used it myself, but PG bouncer might be useful to you in this case.
The number of requests still feels slow, and it isn't clear to me from the blog post whether that is DB limited or CPU limited on the application servers. Even with writes on each access Postgres should still be bored at that kind of load.
Yea, our IO and CPU of our Postgres instance is around 20% currently. We haven't hit too many issues with Postgres, so haven't delved too deeply into the performance.
I think people seeing performance posts are used to people pushing huge numbers. Our intent here was to show that using standard off the shelf tools with a tiny bit of architecting, you can hit huge performance numbers at a reasonable cost. We have lots of various ways to shave performance, but we're pretty sure we could scale 2-3x with the same stack without a ton of work.
Postgres is mostly bored (CPU sub 20% utilized) with 60 write requests per second which is normal peak traffic. Even traffic spikes to 100-120 don't usually change that much.
As our ad network grows though, everything has to grow pretty linearly (writes, reads, requests, etc.) and I hope our approach will continue to work well even with double or triple these numbers.
Fairly common practice for Postgres setups is to sit pgbouncer (https://www.pgbouncer.org/) between your app process and your Postgres instance.
Connection setup/tear-down is cheap in MySQL but expensive in Postgres.
I don't think they need 100 more current connection. Assume one process take 1 connection, only several connection are required.
I think there must be some misconfiguration there. otherwise, the throughout should not be that low.
If possible, the author should setup a demo (contrived query, but similar to production scenario). From there, others can give valid suggestion or improve the code and configure.