An Astro-based frontend loading media from AWS S3 via presigned URLs suffered from redundant network requests, leading to slow page load times and high bandwidth usage.
Issue
The inspire gallery page experienced 6-10 second load times on every refresh due to:
- Repeated API calls for presigned URLs for each media item.
- 3-5MB of S3 media downloaded per page load (e.g., images and videos).
- A Service Worker configured with a
networkOnlystrategy that bypassed caching, ignoringCache-Controlheaders.
Culprit
The Service Worker was configured to bypass caching for all API requests, preventing the caching of presigned URL responses and S3 media files. This design forced fresh downloads on every page load, despite the presence of valid caching headers.
Solution
A three-layer caching system was implemented to address these issues:
1. Service Worker Cache Layer
Modified the Service Worker to introduce:
- A 7-day cache for presigned URL API responses, aligning with AWS presigned URL time-to-live (TTL).
- Indefinite caching for immutable S3 media files (e.g., images, videos).
- Logic to detect and handle presigned URL API requests and S3 media files separately.
2. localStorage Fallback Layer
Added client-side caching in the Astro page component with:
- A 7-day validation for cached URLs.
- Automatic cleanup of expired or outdated cache entries.
- Graceful fallback to API calls if both cache layers fail.
3. Performance Results
| Metric | Before | After (Subsequent Visits) |
|---|---|---|
| Page Load Time | 6-10 seconds | 0.5-1 second (95% faster) |
| API Calls/Refresh | 20+ requests | 0 requests (100% reduction) |
| Data Transfer/Refresh | 3-5MB | ~50KB (99% reduction) |
| Cache Hit Rate | 0% | >90% |
The solution was verified using browser DevTools to confirm cached responses and implemented cache invalidation through version bumping to ensure updates.