PrepZone Logo
PrepZone

CDN, Edge Caching, and Anycast

Push static assets and read-heavy API responses closer to users — ShardPay's receipt PDF delivery.

Why this matters

  • Edge caching cuts latency and origin load for read-heavy assets.
  • Cache invalidation is still one of the hard problems.
  • Anycast routes users to the nearest healthy edge.
  • Financial APIs and static assets need different caching strategies.

CloudFront edge delivery

nearest PoPMISS onlyCLIENT
Viewer (Tokyo)GET segment.ts
NETWORK
CloudFrontedge PoP · HIT
STORAGE
Amazon S3streamhub-media
Video segments cached at PoPs; S3 origin fetch only on cache miss.

Edge vs origin

A CDN (Content Delivery Network) is a geographically distributed cache that stores copies of content close to users. Instead of every receipt PDF request traveling from Singapore to Virginia, the CDN serves it from a PoP (Point of Presence) in Singapore — cutting latency from 200ms to 15ms and reducing origin load by 90%+.

ShardPay's transfer APIs (POST /v1/transfers) always hit origin — they are dynamic, consistency-sensitive, and non-cacheable. Receipt PDFs, merchant logos, and compliance documents are static or semi-static, perfect for edge caching with appropriate TTL and cache keys.

CDN concepts

  • CDN PoP (Point of Presence) — edge cache node in a geographic location, typically 50–200 worldwide for major CDNs. ShardPay's CDN has 180+ PoPs; a merchant in Tokyo gets receipts from the Tokyo PoP, not US-East origin.
  • Cache-Control — HTTP headers that tell the CDN how long to cache (max-age=3600), whether to revalidate (must-revalidate), and who can cache (public vs private). ShardPay sets Cache-Control: public, max-age=300 on receipt PDFs (5-minute TTL).
  • Anycast — the same IP address announced from many locations; BGP routes the user to the nearest healthy PoP. ShardPay's CDN uses anycast so cdn.shardpay.com resolves to the closest edge without client-side geo-routing logic.
  • Origin shield — a mid-tier cache between edge PoPs and origin, reducing origin hits when many PoPs request the same content. ShardPay's origin shield absorbs 95% of cache-miss traffic during a popular merchant's receipt re-download spike.

What to cache and what not to cache

The rule is simple: cache immutable or eventually-consistent reads; never cache writes or strongly-consistent reads. ShardPay's caching policy:

ContentCacheable?TTLCache key
Transfer API responsesNo——
Balance lookupsNo——
Receipt PDFsYes5 minmerchantId/transferId
Merchant logosYes24 hrmerchantId
Compliance documentsYes1 hrdocId
API JSON schemasYes1 hrschemaVersion
  • Transfer API responses

    Cacheable?No
    TTL—
    Cache key—
  • Balance lookups

    Cacheable?No
    TTL—
    Cache key—
  • Receipt PDFs

    Cacheable?Yes
    TTL5 min
    Cache keymerchantId/transferId
  • Merchant logos

    Cacheable?Yes
    TTL24 hr
    Cache keymerchantId
  • Compliance documents

    Cacheable?Yes
    TTL1 hr
    Cache keydocId
  • API JSON schemas

    Cacheable?Yes
    TTL1 hr
    Cache keyschemaVersion

ShardPay CDN caching policy

Caching a balance lookup would serve stale data — a user sees $100 after transferring $50. Caching a receipt PDF is safe: the PDF content is immutable once generated.

Walkthrough: receipt download during peak

A merchant downloads 10,000 receipt PDFs for tax filing. Without CDN, 10,000 requests hit ShardPay's origin API, adding load during an already-busy period. With CDN: the first request per unique PDF fetches from origin and caches at the edge PoP. The next 9,999 requests for the same PDFs serve from cache at 15ms instead of 200ms. Origin load: ~500 unique PDFs (not 10,000).

Java
// ShardPay receipt service — cache-friendly response headers
@GetMapping("/v1/receipts/{transferId}")
public ResponseEntity<byte[]> getReceipt(@PathVariable String transferId,
                                          @RequestHeader("Authorization") String token) {
    Receipt receipt = receiptService.generateIfAbsent(transferId);  // immutable once created

    return ResponseEntity.ok()
        .header("Cache-Control", "public, max-age=300, stale-while-revalidate=60")
        .header("ETag", receipt.etag())
        .header("Vary", "Authorization")  // different merchants see different receipts
        .contentType(MediaType.APPLICATION_PDF)
        .body(receipt.pdfBytes());
}

Cache invalidation strategies

Cache invalidation is notoriously hard. ShardPay uses three strategies depending on content type:

TTL-based expiry — simplest; let the cache expire after max-age. Works for logos and compliance docs that change rarely. A logo update takes up to 24 hours to propagate — acceptable for non-critical assets.

Active purging — call the CDN's purge API when content changes. ShardPay purges a merchant's logo cache immediately after upload, so the new logo appears within 30 seconds globally.

Versioned URLs — include a content hash or version in the URL (/logos/merchant-42/v3.png). New version = new URL = automatic cache miss. ShardPay uses versioned URLs for API JSON schemas so clients always fetch the latest contract.

Caching patterns

  • Cache-aside — application checks cache first, fetches from origin on miss, writes to cache. ShardPay's receipt service lets the CDN handle this transparently via Cache-Control headers.
  • Stale-while-revalidate — serve stale content while fetching fresh copy in background. ShardPay uses stale-while-revalidate=60 on receipts so users never wait for revalidation.
  • Cache key design — include all dimensions that affect the response. ShardPay's receipt cache key includes merchantId and transferId so merchants never see each other's receipts.
  • Negative caching — cache 404 responses briefly to protect origin from repeated lookups for non-existent resources. ShardPay caches 404s for 60 seconds on receipt endpoints.

CDN for dynamic content

Some "dynamic" content benefits from edge caching with short TTL. ShardPay's merchant dashboard status page (GET /v1/merchants/{id}/status) returns semi-static data (account verified, limits configured) that changes at most once per hour. A 60-second CDN TTL reduces origin load by 80% without meaningful staleness.

True dynamic content — transfer processing, balance queries, fraud checks — must never be CDN-cached. The cost of serving a stale balance far exceeds the latency savings. When in doubt, mark it Cache-Control: private, no-store.

Quick recall

Everything you need if you only revisit this box.

  1. CDN helps read-heavy, immutable content — receipts and logos, not transfers.
  2. Cache-Control headers drive TTL; versioned URLs avoid invalidation complexity.
  3. Anycast routes users to the nearest PoP; origin shield protects backend from miss storms.

Test yourself

Answer these before moving on — recall is what makes it stick.