GraphQL CDN caching

Pahlevi Fikri Auliya
HIJUP Engineering
Published in
2 min readOct 18, 2018

CDN adalah cache servers yang tersebar di berbagai lokasi dengan tujuan mendekatkan server dengan visitors. Main server bisa jadi terletak di Jepang, tapi ketika visitors datang dari Indonesia, CDN yang di Singapore yang akan serve. Begitu pula jika visitors datang dari US, CDN di US yang akan serve. Sehingga latency bisa diminalisir dan load di main server bisa dikurangi.

CDN pada umumnya — secara out of the box — melakukan caching terhadap request GET (idempotent) dan menggunakan URL sebagai cache keynya

Salah satu kesulitan caching GraphQL di edge server adalah komunikasinya yang by default menggunakan POST. Di mana tidak semua provider supports caching POST request. Selain itu, POST — by convention — tidak idempotent, sehingga perlu dipilah-pilah POST request mana yang boleh dicache.

Ada 2 metode yang kami terapkan untuk solve itu:

Cache di main server

Simply gunakan Redis/Memcached dengan key = hash(graphql_query & variable) dan value = response. Kelemahan cara ini:

  • Request akan tetap HIT main server
  • Latency lebih tinggi

Automatic Persisted Queries

Instead of mengirim POSTgraphql_query + variable ke server, client mengirim GEThash(graphql_query) + variable. Server akan mencari keyhash(graphql_query) di cache, di mana valuenya adalah graphql_query

https://www.apollographql.com/docs/guides/performance.html#Automatic-Persisted-Queries

Jika tidak ditemukan di cache, server akan request client untuk mengirimkan POSTgraphql_query + variable. Memang akan ada 2x round trips, tapi ini hanya terjadi ketika graphql_query belum tersimpan di cache server. Seandainya kita memiliki 200 jenis graphql_query, hanya 200 requests pertamauntuk semua visitors — yang mengharuskan round trips GET dan POST.

Karena menggunakan GET dan URL paramsnya juga singkat (hanya hash dan variable), caching bisa dengan mudah dipasang di CDN.

Jika menggunakan Apollo client library, caranya simply tambahkan

createPersistedQueryLink({ useGETForHashedQueries: true })

Result:

Kiri: tanpa CDN, Kanan: dengan CDN

--

--