Geo routing based on DNS is the entry point to ensure each region is benefiting the low latency due to locality
Under each LB for each region there's a similar structure in place.
API GW layer takes care of typical concerns like SSL termination, user auth, rate limiting; it also splits writes and reads since system will be reads intensive; provides business analytics and operational monitoring and logging.
Whole system is stateless.
"Create short URL" request goes to ShortenService. Based on the chosen algorithm a short URL is created and stored in the Persistent Store (also added to the Redis cache with a default TTL of say 1 week - this depends on how much available resources goes into the in-memory component).
A DB synchronization service could be run in the background to make persistence store layer consistent accross all regions.
API GW splits reads and writes. For reads API GW calls the Redis cache. If it's a hit it returns the short URL(potentially prolonging the TTL), if it's a miss it goes to ShortenService layer to fetch it form persistent store, serves it to the client and inserts it into the cache.
ShortenService layer generates the shortUrl value. If considering case-sensitive alpha-numeric values to build up the shortUrl string we can ensure unique values by generating unique ID for each new long URL and do a base 62 (0-9a-zA-Z) conversion. This way we ensue uniqueness and avoid possible hash space collisions (could arise if we would hash the long URL).
Before creating a short URL Shorten service checks to see if the longURL is already in the DB -> can use Bloom filter for speed.