GraphQL caching ①導入の背景と目的

# はじめに
GraphQL cachingとは、GraphQL APIのレスポンスをCDNでキャッシュすることにより、GraphQLサーバーの負荷をオフロードし、APIを高速化するキャッシュ層です[^1]。

Amazon CloudFrontを使用して、ALB+ECSで構成されるGraphQLサーバーのレスポンスをキャッシュする仕組みを、[LOWYA](https://www.low-ya.com/)という自社ECサイトへ導入したので、以下の三本立てのシリーズで記事を書いていきたいと思います。

①導入の背景と目的
[②AWS Prototyping program を利用した開発](https://qiita.com/datahaikuninja/items/e3c5302602c38b6a8b71)
[③プロダクションリリースまでに解決した課題、導入による効果](https://qiita.com/datahaikuninja/items/d00316226910f3df2eb8)

本記事は、①導入の背景と目的 の記事です。

なお、本記事を含む三本立ての記事の公開には、JAWS-UG SRE支部の第四回で登壇した内容を補足する目的があります。気になる方は登壇資料もご覧ください。

https://speakerdeck.com/datahaikuninja/lowyaniokerufu-he-dui-ce-togao-su-hua-graphql-caching-on-amazon-cloudfront-with-aws-prototyping-program

### 導入効果について
先に③の記事で紹介する導入効果について書いておくと、CloudFrontのコスト増加額よりECSのコスト削減額が上回ったためAWSの総コストを減らすことができ、フロントエンドで計測したAPIのレスポンスタイムが最大で52%改善しました。
よければ、②と③の記事もお読みいただけたらと思います。

## 想定読者
以下の読者を想定しています。
- GraphQLをCDNでキャッシュする方法に関心がある人
- GraphQLを使用する開発者
- サイト・サービスの可用性やパフォーマンスの課題に取り組むSRE・インフラエンジニア

本記事の内容は、以下のような場合は参考にならないかもしれません。
1. AWS 以外のクラウドサービスを利用している、もしくは CDN は Akamai や Fastly を利用している
1. AppSync を使用している

本記事の前提を記載しておきます。
- AWS を利用する
- CloudFrontのオリジンとなるGraphQLサーバーは ALB + ECS（EC2でも可）で構成されている

# 導入の背景と目的
## GraphQL caching とは
GraphQL cachingとは、GraphQL APIのレスポンスをCloudFrontにキャッシュすることにより、GraphQLサーバーの負荷をオフロードし、APIを高速化するキャッシュ層です。

キャッシングによってGraphQLサーバー（オリジン）のインフラコスト削減、スパイク耐性の向上が期待できます。

## 導入の背景
GraphQLサーバーの負荷対策、AWSのコスト増加、近い未来のスケーラビリティに課題を感じていたためです。
吹き出しが現在の負荷対策で、赤色の楕円は課題に感じていたことです。
![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344652/ea809564-dabd-245e-f5e8-e82a5d813f10.png)

### GraphQLサーバーの負荷対策
アクセス集中（スパイク）が予想されるときは事前にスケールアウトやスケールアップを実施しますが、予想外の負荷に対しては、Auto Scalingが頼りです[^2]。
Fargateの起動時間は改善されてきていますが[^3]、スパイクによる負荷増加にターゲット追跡スケーリングが間に合わず、レスポンスが遅延またはエラーが発生してしまうケースがありました。

### AWSのコスト増加
LOWYAバックエンドのインフラはECSのCapacity Providerを使用しており、常駐タスクとスポットタスクのハイブリッドな構成です。常駐タスクのみで起動する場合と比較するとコストの増加を抑えることができますが、数百台のタスクを起動するのである程度の費用増加は避けられません。

Auroraについても、スパイクが発生するイベントの前〜サイトへのアクセス数が平時の水準に戻るまでスケールアップするので、コストが増加します。

### 近い未来のスケーラビリティの課題
スケールアップ/スケールアウトは近い未来に限界を迎える可能性があります。

データベースの参照系の負荷に対しては、Auroraリーダーエンドポイントを利用して、リーダーインスタンスを増やすことで対策できますが台数にもインスタンスサイズにも上限があります。費用も高くなるので、より費用が安い方法で負荷対策ができた方が好ましいです。
起動できるECSタスク数の上限にぶつかることはかなり稀だと思いますが、クォータにぶつかる可能性もゼロではないことは考えておかなくてはいけません。

## 導入の目的
上記の課題の改善を期待して、**「誰が見ても同じ（同じであるべき）レスポンスをキャッシュすること」** が狙いです。

キャッシングによってオリジンの負荷がCDNへオフロードされたら、開発者がアプリケーションやデータベースのクエリをカリカリにチューニングしたり、バックエンドのインフラを単にスケールアップ/アウトするより安い費用で負荷対策ができるかもしれません。

図の青色のコメントは改善が期待できるポイントです。
![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344652/20853662-d91f-2d71-df74-c6c52a3848c7.png)

# 本記事のまとめ
本記事では、GraphQL cachingの背景と目的を共有しました。
CloudFrontを使用して、「誰が見ても同じ（同じであるべき）レスポンス」をキャッシュすることができれば、GraphQLサーバーの負荷を軽減するだけでなく、高速化も期待できます。

次の記事では、GraphQL cachingをどのように開発したのか、経緯について書きたいと思います。

[^1]:「GraphQL caching」 という用語は、Akamai のBlogで使われています。
https://www.akamai.com/ja/blog/developers/graphql-caching
キャッシュ層は必ずしもCDNに限りません。例えばDBの手前に ElastiCache を配置してクエリ結果をキャッシュすることもできるでしょう。本記事の関心は、CDNでのキャッシュです。
[^2]:Aurora リーダーインスタンスのスケールアウトは参照系処理の負荷対策に対して有効な方法ですが、現状はアプリケーション側がリーダーエンドポイントを参照する作りになっておらず、この方法は使用できないため構成図には記載していません。
[^3]:2022年4月にFargateの高速スケーリングが可能になりましたが、それでもエラーが発生するケースに遭遇したことはあります。
https://aws.amazon.com/jp/about-aws/whats-new/2022/04/aws-fargate-delivers-scaling-applications/