Nice architecture sketch. The part that bites operators is cache-key design once you leave static assets. Including $scheme$request_method$host$request_uri is a solid default, but any Vary on cookie/authorization or per-tenant response means you either bypass cache for those locations or fold the discriminating input into the key. I have seen edges happily serve user A’s JSON to user B after a well-intentioned proxy_cache_valid 200 30s on an authenticated API.
Operationally I always add_header X-Cache-Status $upstream_cache_status always so HIT/MISS/BYPASS is visible without packet captures. Short TTLs with proxy_cache_lock help thundering herds after deploy; purge strategy matters more than raw TTL when HTML is involved. On the DNS side, anycast or geo answers only help if each edge has warm cache for the same keys — otherwise you just move the miss closer to the user while origin still pays. Before widening TTL I compare origin request rate per region after a purge, not just latency percentiles.