I need to create a FastAPI python app. Tech stack is FastAPI python app, Postgres DB, Redis for caching/rate limiting, etc Debezium and Apache Pulsar message broker for websocket message broadcasting. It will be a micro-service that should handle some sort of point system. I already have a separate Auth service that handles authentication and store all the user's data. So all the microservices just share a secret in env variables to encode JWT token generated by this Auth service. This new microservice won't be an exception and will use same auth mechanism. Service itself need to handle points mechanism which basically give a user opportunity to claim some number of points once in a while, the time of claim availability should depend on a streak that user has. So basically the first day user login into app they have a 24 hours cooldown after claim. But each daily login streak reduce this cooldown by 1 hour till the streak is 16 or more, after that cooldown is 8 hours and it couldn't go lower. So user can claim points by clicking the button and the cooldown starts, but the cooldown time depends on the login days streak. This service also will handle referral system so user will get 10% from its referral points and 2% from a referral of its referral points. I thought to make some rate limiting to prevent claim of points more than once a day without triggering an additional DB call. But I don't know how to make the most efficient referral system. I also need to say that this should be the most efficient solution that can handle very high load, like 10000 rps and 1000000 users.

It also should have cache invalidating mechanism and if updating cache values it should make it atomic by utilizing Lua scripts.

Regarding the points claim itself: So basically we can have one of two approaches here, and the question is which one of them is better performance-wise, will handle more RPS and will be more robust? The 1st approach: User claim points. Because beside user's points we need also to increment his referrer and his referrer's referrer points also and we don't know who are they at the moment and don't want to make additional read calls to DB we pass this task to Celery worker who will run the task that will make 1 DB call with update for all 3 of them and increase their points, but due to concurrency and potential data loss we need to make this task to use "select for update" Postgres option to lock all 3 users while we are updating them. The 2nd option: We write all claim requests as events into separate DB, using Debezium as a connector for this DB so it will automatically stream all the records into our Apache Pulsar topic, our asynchronous worker will consume messages from this topic as a queue 1 by 1 and run the same update as in the 1st approach (make 1 DB call with update for all 3: user, his referrer and his referrer's referrer) but due to the consumer acknowledge control we could consume this data 1 by 1 and there for we don't need to use "for update" Postgres lock because we 100% sure that data has been consumed 1 by 1. The problem with this approach that we don't utilize multithreading and asynchronous work in that case because we need to make sure that this data is consumed 1 by 1. Maybe you can give me some better approach to be sure that concurrency resolved but we could still make those updates asynchronous? Maybe there is a common approach for those type of application?

Also a few important notes:
1. We have only user_id in initial request because we do not make a call into DB to get the user, we use user_id from JWT auth token(because it is easier for us cause we need to decode JWT anyway to make sure that it is a valid call so we can reduce DB calls here), but we need to update user's points, as well his referrer points and his referrer's referrer points here. 
2. User model should have 2 fields: points and ref_points. The points are the real points you get, and ref_points is a field that collect you referrals points that could be claimed by another request. SO basically we update User.points and his referrer and his referrer's referrer ref_points with 10% and 2% of user's points. So there should be a claim task that handles basically two cases: straight up claim points, that also increase ref points of referrers and claiming ref_points which increase only you points by you ref_points amount and then decrease you ref_points to 0.
3. It would be great to have some sort of Optimistic lock up using Etag or versioning with retries to ensure that there are no data loss.