-
Notifications
You must be signed in to change notification settings - Fork 5
Scalability discussion #11
Comments
current idea (TCN) is put a CDN in front of the app. the backend itself doesn't need that much. |
https://github.com/awesome-selfhosted/awesome-selfhosted#faasserverless Edit: this link is to inform about different server less opensource solutions. |
The dp3t whitepaper mentions an estimated data size, maybe those numbers help to come to a data-driven decision (especially with respect to database size and upload traffic):
|
My take at least for deploying the backend: A managed Kubernetes cluster on a public cloud provider, e.g. GCP, AWS, Azure or DigitalOcean. It's not especially cheap, but very reliable and flexible.
Deploy with horizontal autoscaling, both for the nodes (cluster size) and deployments (containers running the application). In addition, I would add a circuit-breaker on top of the backend. An additional caching layer could either be done in the cluster, or be handled by a dedicated CDN provider.
Probably hardest to scale, there's a Helm chart for high availability https://github.com/bitnami/charts/tree/master/bitnami/postgresql-ha.
Rate limiting at Ingress level, e.g. https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limiting. Additionally, something like CloudFlare could definitely help as the DDoS protection is in their free tier. Downside is that all traffic goes through their servers, so no clue if that's a blocker w.r.t. privacy. |
I would also recommend K8S for application hosting, it will make scaling fairly easy. There are alternative like server less like AWS Lamda that should also be looked at. Regarding to the scalability of PostgreSQL I would mostly recommend not hosting it in the k8s cluster but using the hosted option by the cloud provider. It takes a lot of maintenance work from you like updating and backups. From what I understand from the current database it won't be very complex but in case many people use the app the database will get bombarded by requests. A good solution for that would probably to add a Redis cache between the application and the database. That should take of the load and scale's pretty well. |
I love serverless, however Lambda can become very expensive as the API Gateway costs ramp up quickly with high numbers of invocations.
Such an approach - where the application is aware of the caching - reminds me of how Netflix solves this problem. Basically, the application pushes changes to their caching service, which in turn is in charge of allowing all incoming requests to be served. Their tech stack is mature and proven to scale- they have been using it at scale for several years now. However, it's also rather complex and only works for data which can be "produced" - you need to pre-compute all cached data as there's no way to back-propagate cache misses. |
I had a simpler cache mechanism in mind. Just a query result cache. Basically if you want to do a query, first you do a request to a key in the Redis cache. If the key exists you return the data stored with that key, if not you do the query on the DB server. When you get a result form the DB server you write that data to the Redis cache and with the key and a invalidation time. AWS has some some information about this: https://d0.awsstatic.com/whitepapers/Database/database-caching-strategies-using-redis.pdf The result of this will be as followed: This is just an example and not realistic but its a basic way of make sure a database doesn't get overwhelmed by your own application. Redis really fast at returning these results as all the data is stored in memory and it has nice scaling options. The Netflix way of doing it is probably better, but also a lot more complex. I would start out with a easy cache solution and see if that words and only add complexity if needed. |
+1 for referencing patterns. I agree that a simple solution is preferable until it reaches its scalability issues. One issue which I do not see how it's explicitely covered in AWS' whitepaper is how to make that when there's a cache miss similar concurrent request will not also hit the DB. Anyway, I don't see any real blockers, just unanswered questions for each of which already various solutions come to mind. Not something to worry about right now. |
Good catch! This problem (which is a version of the Thundering Herd Problem) is most easily solved at the cache layer, so depending on where you implement caches, it might be possible to use an existing solution. Alternatively, given you have implemented retry and exponential backoff on the client side, the server can afford to not answer / defer answering a request. This allows you to use:
|
General issue for discussion about scalability and other issues that come with it
The text was updated successfully, but these errors were encountered: