This article details a banking app's engineering decision to reduce Google Maps API costs and improve latency by implementing a two-layer caching strategy. The solution involves an internal database for persistent storage of map data and Redis for fast lookups of frequently accessed, fresh information, carefully balancing cost reduction with data freshness and compliance.
Read original on Dev.to #systemdesignA banking application faced high costs and latency due to frequent calls to the Google Maps API for its "nearby branches and ATMs" feature. Each user interaction, even for data that might have been recently fetched, resulted in a new external API request. The core problem was treating every lookup as if it were the first, leading to redundant requests for reusable information.
The first step was to store Google Maps data in an internal database after the initial fetch. Subsequent requests would first query the internal database. If the data was present, the external Google Maps API call was avoided. This approach significantly reduced external API calls, lowered costs, and provided faster responses for cached data. However, a challenge arose regarding the performance of initial lookups against the internal database if the data wasn't found, potentially increasing latency for uncached requests.
To address the latency concern for uncached data, Redis was introduced as a faster, in-memory layer. Redis acts as a pointer cache, indicating whether specific requested data is *not* present in the internal database. This means:
flowchart TD A[User opens map] --> B{Check Redis Cache} B -->|Pointer exists: data unavailable locally| C[Request Google Maps API] C --> D[Return response to user] B -->|Pointer does not exist: data may be in database| E[Request Bank Server] E --> F{Data found in database?} F -->|Yes| G[Return stored data] G --> D F -->|No| H[Request Google Maps API] H --> I[Store eligible data in bank database] I --> J[Remove corresponding Redis pointer] J --> K[Return response to user]A critical aspect of data reuse is managing freshness. Location data changes, requiring a strategy to update or invalidate stale records. The article emphasizes distinguishing between availability, freshness, and permission (Google Maps API terms prohibit certain types of caching). Different fields (e.g., Place IDs vs. lat/long) have varying retention rules. The system must ensure that Redis, while providing speed, never serves as a inconsistent source of truth and that stale data is not reintroduced.
Key Takeaways for Caching Decisions
The decision to use Redis was highly targeted: latency was critical for this specific feature, the access pattern (repeated lookups of the same data) was a perfect fit, and Redis complemented the database without replacing its role as the source of truth. Implementing a caching layer indiscriminately across an entire system can introduce unnecessary costs and complexity without solving relevant problems.