1) Sign session ids that you issue and reject requests that don't have a valid signature. This can be done entirely in software at the router level without any I/O
2) For each session, do authentication. Unauthenticated sessions get lower caps.
3) For authenticated sessions, have various schemes for X units of Y in Z seconds. And then use this database - sharded by Y - before each expensive Y.
4) Y should be prefixed with a user role or payment plan or whatever, followed by the actual resource id. So people can buy another payment plan.
5) Possibly let people pay to access a resource beyond the quota.
6) Make clients recognize quota errors and retry with exponential backoff.
7) Host static resources in the app, fallback to a CDN, and only host dynamic resources on your own source servers.
8) Wherever possible, cache things in the client, keeping in mind that you have to evict the lease recently used items eventually.