Private-origin CDN and a shared upload directory
A media company keeps 40 TB of thumbnails and CSS/JS in Object Storage in the Korea region. Users are in Korea, Japan, and Southeast Asia; 70% of requests come from outside Korea. Monthly origin egress is 120 TB, and the buckets must not be public. Only the CDN may read them, and paid content needs signed URLs. A Singapore analytics team needs a daily 300 GB Parquet export. Twenty web servers in two availability zones also need a shared read/write directory for user uploads before those uploads are committed to Object Storage. Security requires that the Object Storage endpoint never be exposed to the public internet. The team has a 2 Gbps private inter-region link and four weeks to cut egress cost without breaking signed URLs or changing the web application's upload API. The analytics team can tolerate a six-hour delay but not a full re-ingest.
1. Design the delivery path for public CSS/JS/thumbnails and paid content. Where do signed URLs terminate, and how do you keep the bucket private?
Read the worked answer
- Put Global CDN in front of the buckets. Keep every bucket private and grant origin read access only to the CDN, not to the public internet. The bucket endpoint must not be reachable by users.
- For public assets, the CDN caches thumbnails, CSS, and JS at edge locations. Origin egress falls because most requests terminate at the edge; 70% of demand being outside Korea makes this the largest cost lever.
- For paid content, terminate signed URL validation at the CDN edge, not at the bucket. Issue short-lived tokens, for example five minutes, bound to the user session and the requested object. The CDN rejects invalid or expired tokens before it contacts the origin.
- Critical cache detail: if the token is in the query string, configure the cache key to ignore the token. Otherwise every signed URL is a unique cache object, cache hit ratio collapses, and origin egress can rise. If the CDN supports token headers or cookies, prefer that.
- Keep the origin private even for public assets. A public bucket would let anyone bypass the CDN, skip signed URL checks for paid objects, and generate uncontrolled egress.
2. The 20 web servers need a shared read/write directory before objects are committed. Compare NAS and direct-to-Object-Storage pre-signed uploads, and recommend one.
Read the worked answer
- NAS gives a POSIX file system with shared locking and atomic rename. It is the right choice only if the application truly needs those semantics. Cross-zone mounts add latency and make the NAS a shared dependency for both zones; a zone failure can stop uploads even if the web tier survives.
- Direct-to-Object-Storage upload is better for this case. The web server issues a short-lived pre-signed upload URL, the client writes directly to Object Storage, and the application commits metadata only after the upload completes. The web tier no longer buffers files or shares a file system.
- This design removes the cross-zone directory, scales with Object Storage, and keeps the bucket private because the pre-signed URL is scoped and time-limited. Add asynchronous virus scanning and a commit state machine so an uncommitted object is never served.
- Recommendation: use pre-signed direct uploads and reserve NAS for workloads that require POSIX semantics, such as a shared temporary build directory. If NAS is unavoidable, place writers in one zone or partition files by writer to avoid cross-zone lock contention.
3. The Singapore analytics team needs 300 GB per day over private connectivity. How do you move it without public internet and without blowing the egress budget?
Read the worked answer
- Arithmetic: 300 GB per day is about 2.4 Tb. At 2 Gbps, the theoretical transfer is about 20 minutes; at 60% efficiency, about 33 minutes. The link is not the bottleneck, so schedule the job off-peak rather than buying more bandwidth.
- Use the 2 Gbps private inter-region link, not the public internet. Write the Parquet export to an Object Storage bucket in Singapore, or use cross-region replication if the service supports it for the chosen bucket. Do not serve analytics files through the CDN.
- Reduce volume before transfer: partition by date and tenant, push aggregation down, and send only columns the analytics team needs. If 300 GB can become 60 GB of aggregated Parquet, egress drops by 80% with no loss of required output.
- The analytics team tolerates six hours, so a scheduled transfer at 01:00 with retry and checksum verification is acceptable. Keep the Korea bucket as the source of truth and expire the Singapore copy after the reporting window. For an initial backfill, use a bulk transfer appliance rather than saturating the link for days.