- Figmaのデータベースチームが、Postgresスタックを水平シャーディングした9か月にわたる道のりと、ほぼ無限のスケーラビリティを可能にした方法を整理
FigmaのPostgresスタック水平シャーディングの旅
- Figmaのデータベーススタックの規模は2020年以降ほぼ100倍に増加: これは事業拡大を意味する前向きな課題である一方、技術的な挑戦も生み出した。2020年にはAWSの最大の物理インスタンス上で単一のPostgresデータベースを運用していたが、2022年末までにキャッシュ、読み取りレプリカ、そして垂直分割された複数のデータベースを含む分散アーキテクチャを構築した。
- 垂直分割: 関連するテーブル群をそれぞれ独自の垂直パーティションに分離することで、段階的なスケーリングの利点を得て、成長に先回りできる十分な余裕を維持した。たとえば、「Figmaファイル」や「組織」のような関連テーブル群を、それぞれ独自の垂直パーティションに分割した。
- 水平シャーディングへの移行: 垂直分割だけでは限界があると認識した。CPU使用率の低下に焦点を当てた初期のスケーリング施策の後、より大規模で多様になったフリートにおけるさまざまなボトルネックの監視を開始した。データベースのスケーリング限界を、CPUやIOからテーブルサイズ、書き込まれた行数に至るまで多面的に定量化した。これらの限界を特定することは、シャードごとにどれだけの余裕があるかを予測する上で重要だった。
- テーブルサイズの限界: 一部のテーブルは数TB、数十億行を抱えるようになり、単一データベースでは扱いにくい規模に達した。この規模では、Postgresのvacuum処理(トランザクションIDの枯渇による停止を防ぐための必須バックグラウンド処理)の最中に信頼性へ影響が出た。最も書き込みの多いテーブルは、AmazonのRelational Database Service(RDS)がサポートする最大IOPSを間もなく超える見込みだった。これは垂直分割では解決できない問題であり、データベースの崩壊を防ぐために、より大きな解決策が必要だった。
規模拡大のための足場づくり
- 開発者への影響を最小化: 複雑なリレーショナルデータモデルの大部分を吸収し、アプリケーション開発者がコードベースの大規模なリファクタリングではなく、Figmaで魅力的な新機能を構築することに集中できるようにした。
- 透過的な拡張: 将来スケールさせる際に、アプリケーション層で追加変更を行わなくて済むようにした。つまり、テーブルを互換性のあるものにする最初の事前作業の後は、将来の拡張がプロダクトチームに対して透過的に行えるようにした。
- 高コストなバックフィルの回避: Figmaの大規模テーブル、あるいはすべてのテーブルに対するバックフィルを伴う解決策は避けた。テーブルの規模とPostgresのスループット制約を考えると、そのようなバックフィルは数か月かかる見込みだった。
- 段階的な進行: 主要な本番変更のリスクを抑えつつ、段階的にリリースできるアプローチを特定した。これにより重大な障害リスクを減らし、データベースチームが移行中もFigmaの信頼性を維持できるようにした。
- 一方向の移行を回避: 物理シャーディングの作業が完了した後でも、ロールバックできる能力を維持した。これにより、未知の変数が発生した際に悪い状態に閉じ込められるリスクを減らした。
- 強力なデータ整合性の維持: ダウンタイムなしでの実装が難しい、または整合性を損なうような複雑な解決策、たとえばダブルライト(double-writes)は避けた。ほぼゼロダウンタイムでスケールできる解決策を求めた。
- 自分たちの強みを活用: 厳しい締め切りのプレッシャーの中で作業するにあたり、可能な限り段階的にリリースできるアプローチを優先した。最も急成長しているテーブルに対しては、既存の専門知識と技術を活用しようとした。
可能な選択肢の探索
- 水平シャーディングデータベースの選択肢を検討: PostgresやMySQLと互換性のある水平シャーディングデータベースには、さまざまな人気のオープンソースおよびマネージドソリューションがある。CockroachDB、TiDB、Spanner、Vitessを評価する過程で検討した。しかし、これらの代替データベースへ移行すると、2つの異なるデータベースストア間で整合性と信頼性を確保するために、複雑なデータ移行が必要になったはずだった。
- 既存の専門性を活用: ここ数年で、RDS Postgresを安定かつ効率的に運用する方法について多くの専門知識を築いてきた。移行中には、そのドメイン知識をゼロから再構築しなければならなかったはずだ。非常に攻撃的な成長率を考えると、残された時間は数か月しかなかった。
- NoSQLデータベースの採用を除外: 会社の成長に伴って一般的に選ばれる別のスケーラブルな解決策はNoSQLデータベースだ。しかし、現状ではPostgresアーキテクチャ上に構築された非常に複雑なリレーショナルデータモデルを持っており、NoSQL APIはそのような多様性を提供しない。エンジニアがほぼすべてのバックエンドアプリケーションを書き換えるのではなく、優れた機能をリリースし、新しい製品を構築することに集中できるようにしたかったため、NoSQLは実行可能な解決策ではなかった。
- 既存のRDS Postgresインフラ上で水平シャーディングソリューションを構築する案を検討: 小規模チームが一般的な水平シャーディング対応リレーショナルデータベースを社内で再実装するのは意味がない。そうすると、大規模なオープンソースコミュニティや専門データベースベンダーが作ったツールと競合することになる。しかし、Figma固有のアーキテクチャに合わせて水平シャーディングをカスタマイズするため、はるかに小さな機能セットでも十分だった。たとえば、シャード間トランザクションの失敗に対処する方法があるため、原子性を保証するシャード間トランザクションはサポートしないと決めた。アプリケーション層で必要となる変更を最小化するコロケーション(colocation)戦略を選択した。これにより、プロダクトロジックの大半と互換性のあるPostgresのサブセットをサポートできるようになった。また、シャーディングされたPostgresとシャーディングされていないPostgresの後方互換性も容易に維持できた。未知の変数に直面した場合でも、シャーディングされていないPostgresへ簡単にロールバックできた。
水平シャーディングへの道
- 水平シャーディングの導入: 水平シャーディングとは、単一のテーブルまたはテーブル群を分割し、複数の物理データベースインスタンスにデータを分散するプロセスである。この仕組みにより、アプリケーション層では水平シャーディングされたテーブルが、物理層では任意の数のシャードをサポートできるようになる。物理シャード分割を実行するだけで常に追加の拡張が可能であり、その作業は最小限のダウンタイムとアプリケーションレベルの変更なしで、透過的にバックグラウンドで行われる。この機能によって、Figmaは残っていたデータベースのスケーリングボトルネックを先回りして解消し、最後に残った主要なスケーリング課題の1つを取り除くことができた。垂直分割が高速道路の速度まで加速できるようにしたのだとすれば、水平シャーディングは制限速度そのものを取り払い、飛べるようにした。
- 水平シャーディングの複雑さ: 水平シャーディングは、それ以前のスケーリング施策よりも一段複雑だ。テーブルが複数の物理データベースにまたがって分割されると、ACID SQLデータベースで当然視されていた多くの信頼性・整合性の性質が失われる。たとえば、特定のSQLクエリはサポートするのが非効率または不可能になり、アプリケーションコードは、クエリをできる限り正しいシャードへ効率よくルーティングするための十分な情報を提供するよう更新する必要がある。スキーマ変更は、すべてのシャードが同期を保てるよう調整しなければならず、外部キーやグローバルに一意なインデックスはもはやPostgresによって強制できない。トランザクションは複数シャードにまたがるようになり、Postgresによってトランザクションを強制できなくなる。これにより、一部のデータベースへの書き込みは成功しつつ、別の書き込みは失敗する可能性がある。プロダクトロジックは、このような「部分コミット失敗」に対して堅牢であるよう注意深く設計する必要がある(たとえば、2つの組織間でチームを移動するとき、データの半分だけが欠けた状態を想像してほしい)。
- 水平シャーディングに向けた複数年の取り組み: 完全な水平シャーディングの実現は複数年にわたる取り組みになると分かっていた。可能な限りプロジェクトのリスクを下げながら、段階的な価値を提供する必要があった。最初の目標は、できるだけ早く本番環境で、比較的シンプルだが非常に高トラフィックなテーブルをシャーディングすることだった。これは水平シャーディングの実現可能性を証明するだけでなく、最も高負荷なデータベースに対する余裕を延ばすことにもつながる。その後、より複雑なテーブル群をシャーディングしながら追加機能を構築できる。最もシンプルな機能セットでさえ、なお相当な作業量だった。最初から最後まで、チームは最初のテーブルをシャーディングするのにおよそ9か月を要した。
私たちの独自のアプローチ
- コロケーション(Colos): 関連するテーブル群を、同じシャーディングキーと物理シャーディングレイアウトを共有するコロケーション(愛称として「コロ」)として水平シャーディングした。これにより、開発者が水平シャーディングされたテーブルとやり取りできる、扱いやすい抽象化を提供した。
- 論理シャーディング: アプリケーション層の「論理シャーディング」と Postgres 層の「物理シャーディング」という概念を分離した。よりリスクの高い分散物理フェイルオーバーを実行する前に、より安全で低コストな論理シャーディングのリリースを行うためにビューを活用した。
- DBProxy クエリエンジン: アプリケーション層で生成された SQL クエリを横取りし、さまざまな Postgres データベースへクエリを動的にルーティングする DBProxy サービスを構築した。DBProxy には、複雑な水平シャーディングクエリを解析して実行できるクエリエンジンが含まれる。DBProxy を通じて、動的負荷分散やリクエストヘッジングといった機能を実装できた。
- シャドーアプリケーション準備性: さまざまな潜在的シャーディングキーのもとで、実際の本番トラフィックがどのように動作するかを予測できる「シャドーアプリケーション準備性」フレームワークを追加した。これにより、プロダクトチームはアプリケーションを水平シャーディングに対応させるために、アプリケーションロジックをリファクタリングまたは削除する必要性を明確に把握できた。
- 完全な論理レプリケーション: 各シャードにデータの部分集合だけをコピーする「フィルタ付き論理レプリケーション」を実装する必要はなかった。代わりに、データセット全体をコピーしたうえで、特定のシャードに属するデータの部分集合に対してのみ読み書きを許可した。
シャーディングの実装
- シャードキー選定の重要性: 水平シャーディングで最も重要な判断の1つは、どのシャードキーを使うかだ。水平シャーディングでは、シャードキーを中心に複数のデータモデル上の制約が追加される。たとえば、ほとんどのクエリは適切なシャードへリクエストをルーティングするためにシャードキーを含む必要がある。外部キーのような特定のデータベース制約は、外部キー自体がシャーディングキーである場合にのみ機能する。シャードキーは、信頼性の問題やスケーラビリティへの影響を引き起こすホットスポットを避けるため、すべてのシャードにわたってデータを均等に分散できなければならない。
- Figma のデータモデルに合わせたアプローチ: Figma はブラウザ上で動作し、多くのユーザーが同時に同じ Figma ファイルで共同作業できる。これは、ファイルメタデータ、組織メタデータ、コメント、ファイルバージョンなどを捉える比較的複雑なリレーショナルデータモデルによって支えられていることを意味する。既存のデータモデルには単一の有力候補がなかったため、すべてのテーブルで同じシャーディングキーを使うことも検討したが、そのためには統一シャーディングキーを追加するための複合キーの作成、すべてのテーブルスキーマへのカラム追加、それを埋めるための高コストなバックフィルの実行、そして大幅なプロダクトロジックのリファクタリングが必要になったはずだ。そこで、Figma 独自のデータモデルに合わせてアプローチを最適化し、UserID、FileID、OrgID のような少数のシャーディングキーを選んだ。Figma のほぼすべてのテーブルは、これらのキーのいずれかを使ってシャーディングできる。
- コロケーション(Colos)の導入: プロダクト開発者にとって扱いやすい抽象化を提供するコロケーションという概念を導入した。コロ内のテーブルは、単一のシャーディングキーに制限される場合、テーブル横断の JOIN と完全なトランザクションをサポートする。アプリケーションコードの大半はすでにこの形でデータベースとやり取りしていたため、アプリケーション開発者がテーブルを水平シャーディング対応に修正する作業を最小限に抑えられた。
- データ分散の均一性を保証: シャーディングキーを選んだ後は、すべてのバックエンドデータベースにわたってデータが均等に分布することを保証しなければならない。残念ながら、選ばれたシャーディングキーの多くは自動増分 ID や Snowflake のタイムスタンプ接頭辞付き ID を使っていた。そのままでは、単一シャードに大半のデータが集中する深刻なホットスポットが生じていたはずだ。よりランダム性の高い ID への移行も検討したが、それには高コストかつ長期間のデータ移行が必要だった。そこで代わりに、ルーティングにはシャーディングキーのハッシュを使うことにした。十分にランダム性のあるハッシュ関数を選べば、データの均等な分布を保証できる。この方式の欠点の1つは、シャードキーに対する範囲スキャンの効率が下がることだ。連続したキーが別々のデータベースシャードへハッシュされるためである。しかし、このクエリパターンはコードベース内では一般的ではなかったため、受け入れ可能なトレードオフだった。
「論理的」な解決策
- 水平シャーディング導入時のリスク低減: 水平シャーディング導入のリスクを減らすため、シャード分割を実行する物理的なプロセスと、アプリケーション層でテーブルを準備するプロセスを分離したいと考えた。そのために「論理シャーディング」と「物理シャーディング」を切り分けた。こうすることで、移行の2つの部分を分離し、独立して実装してリスクを下げられる。論理シャーディングは、低リスクな割合ベースのリリースを通じてサービングスタックへの確信を与えた。バグを見つけたときに論理シャーディングをロールバックするのは、単純な設定変更で済んだ。物理シャード作業のロールバックも可能ではあるが、データ整合性を確保するために、より複雑な調整が必要になる。
- 論理シャーディング後の挙動: テーブルが論理的にシャーディングされると、すべての読み書き処理は、すでに水平シャーディングされているかのように動作する。信頼性、レイテンシ、一貫性の面では水平シャーディングされた状態に見えるが、データ自体は依然として単一のデータベースホスト上に物理的に存在する。論理シャーディングが想定どおりに動作するという確信が得られた時点で、物理シャーディング作業を実施する。これは、単一データベースからデータをコピーして複数のバックエンドへシャーディングし、その後、新しいデータベース群を通じて読み書きトラフィックを再ルーティングするプロセスである。
実用的なクエリエンジン
- 水平シャーディング対応に向けたバックエンドスタックの再設計: 当初、アプリケーションサービスは接続プーリング層である PGBouncer と直接通信していた。しかし、水平シャーディングには、はるかに複雑なクエリ解析、計画、実行が求められる。これを支えるため、新しい golang サービスである DBProxy を構築した。DBProxy はアプリケーション層と PGBouncer の間に位置する。そこには、負荷分散、可観測性の強化、トランザクション対応、データベーストポロジー管理、軽量クエリエンジンを含むロジックがある。
- クエリエンジンの中核コンポーネント:
- クエリパーサー: アプリケーションから送られた SQL を読み取り、抽象構文木(AST)に変換する。
- 論理プランナー: AST を解析し、クエリプランからクエリ種別(INSERT、UPDATE など)と論理シャード ID を抽出する。
- 物理プランナー: クエリを論理シャード ID から物理データベースへマッピングする。適切な物理シャードで実行できるようにクエリを書き換える。
- 「scatter-gather」方式: データベース全体で鬼ごっこをするようなものだ。クエリをすべてのシャードに送り(scatter)、それぞれから答えを集める(gather)。面白いが、複雑なクエリで多用すると、データベースがカタツムリのように遅くなる可能性がある。
- 水平シャーディング環境でのクエリ実装: 単一シャードクエリは、単一のシャードキーでフィルタされる。クエリエンジンはシャードキーを抽出し、クエリを適切な物理データベースへルーティングするだけでよい。クエリ実行の複雑さを Postgres に「押し下げる」形だ。しかし、クエリにシャーディングキーが含まれていない場合、クエリエンジンはより複雑な「scatter-gather」を実行しなければならない。この場合、すべてのシャードへクエリをファンアウトし(scatter フェーズ)、その後で結果を集約する(gather フェーズ)。
- SQL 互換性の簡素化: DBProxy サービスが完全な SQL 互換性をサポートしていたら、Postgres データベースのクエリエンジンと非常によく似たものになっていただろう。API を単純化して DBProxy の複雑さを最小限に抑え、サポートされないクエリを書き換える必要があるアプリケーション開発者の負担を減らしたいと考えた。適切なサブセットを決めるために、テーブルの潜在的なシャーディングスキーマを定義でき、リアルタイムの本番トラフィック上で論理計画ステップを実行できる「シャドープランニング」フレームワークを構築した。クエリとそれに対応するクエリプランを Snowflake データベースに記録し、オフライン分析を実行できる。このデータをもとに、クエリエンジンの最悪ケースの複雑性を避けつつ、最も一般的な 90% のクエリをサポートするクエリ言語を選択した。たとえば、すべての範囲スキャンとポイントクエリは許可されるが、JOIN は同じコロ内の2つのテーブル間で、シャーディングキーに対して行われる場合にのみ許可される。
今後の展望
- 論理シャードのカプセル化: 論理シャードをどのようにカプセル化するかを決める必要があった。別個のPostgresデータベースまたはPostgresスキーマを使ってデータを分割する方法を検討した。残念ながら、これは論理的にシャーディングする際に物理データの変更を必要とし、物理シャード分割と同じくらい複雑だった。
- Postgresビューによるシャード表現: 代わりに、シャードをPostgresビューとして表現することにした。各テーブルごとに複数のビューを作成でき、それぞれが指定されたシャードのデータ部分集合に対応する。形式は次のようになる:
CREATE VIEW table_shard1 AS SELECT * FROM table WHERE hash(shard_key) >= min_shard_range AND hash(shard_key) < max_shard_range). すべての読み取りおよび書き込み操作はこのビューを通じて行われる。
- 既存の非シャーディング物理データベース上へのシャーディング済みビュー作成: 危険な物理リシャード作業を実施する前に、論理的にシャーディングできる。各ビューには専用のシャーディング接続プーラーサービス経由でアクセスする。接続プーラーは依然として非シャーディングの物理インスタンスを指すため、外見上はシャーディングされているように見える。クエリエンジンの機能フラグを通じてシャーディングされた読み書きのリリースを段階的に行うことでリスクを低減し、メインテーブルへトラフィックを戻すことで数秒以内にいつでもロールバックできた。最初のリシャードを実行するまでに、シャーディングされたトポロジーの安全性に確信を持てるようになった。
- ビュー依存のリスク: ビューは性能オーバーヘッドを追加し、場合によってはPostgresクエリプランナーのクエリ最適化方法を根本的に変える可能性がある。このアプローチを検証するため、無害化した本番クエリのクエリコーパスを収集し、ビューあり・なしの両方で負荷テストを実行した。その結果、ほとんどのケースでビューが追加する性能オーバーヘッドは最小限で、最悪の場合でも10%未満であることを確認できた。また、すべてのリアルタイム読み取りトラフィックをビュー経由で送り、ビューありのクエリとなしのクエリの性能および正確性を比較するシャドーリードフレームワークも構築した。その結果、ビューが最小限の性能影響で実用的な解決策であることを確認できた。
トポロジー問題の解決
- クエリルーティングのためのDBProxyのトポロジー理解: テーブルと物理データベースのトポロジーを理解する必要があった。論理シャーディングと物理シャーディングの概念を分離したことで、これらの抽象化をトポロジー内でどう表現するかが必要になった。
- テーブルとシャードキーのマッピング:
users テーブルを user_id シャードキーにマッピングする方法、論理シャードID(123)を適切な論理データベースおよび物理データベースにマッピングする方法が必要だった。
- 垂直パーティショニングとハードコードされた設定ファイル依存: 垂直パーティショニングでは、テーブルを対応するパーティションにマッピングする単純なハードコード済み設定ファイルに依存していた。水平シャーディングへの移行では、より複雑なシステムが必要になった。
- トポロジーの動的変更とDBProxyの迅速な状態更新の必要性: シャード分割中にはトポロジーが動的に変化するため、誤ったデータベースにリクエストをルーティングしないよう、DBProxyが状態を迅速に更新する必要があった。
- トポロジー変更の後方互換性: すべてのトポロジー変更は後方互換であり、サイトのクリティカルパス上に非互換な変更を置かないようにした。
- 複雑な水平シャーディングメタデータをカプセル化するデータベーストポロジーの構築: 複雑な水平シャーディングのメタデータをカプセル化し、1秒未満でリアルタイム更新を提供するデータベーストポロジーを構築した。
- 論理トポロジーと物理トポロジーの分離によるデータベース管理の簡素化: 非本番環境では本番環境と同じ論理トポロジーを維持しつつ、物理データベース数を減らすことでコスト削減と複雑さの低減を実現した。
- トポロジーライブラリによるトポロジー内不変条件の強制: すべてのシャードIDが必ずちょうど1つの物理データベースにマッピングされることなど、トポロジー内の不変条件を強制することで、水平シャーディング構築時のシステムの正確性を維持した。
物理シャーディング作業
- テーブルのシャーディング準備完了後の最終段階: 非シャーディングからシャーディング済みデータベースへの物理フェイルオーバー。水平シャーディングでも同じロジックの多くを再利用できたが、1対1のデータベースから1対Nへ移行するなど、いくつか注目すべき違いがあった。
- フェイルオーバープロセスの耐久性強化の必要性: シャーディング作業がデータベースの一部でしか成功しないという新しい障害モードに備え、フェイルオーバープロセスをより堅牢にする必要があった。
- 垂直パーティショニングで大半のリスク要因をすでに解消: 多くのリスク要因は垂直パーティショニングの段階ですでに低減されていたため、そうでなければ不可能だったよりもはるかに速く最初の物理シャーディング作業へ進むことができた。
水平シャーディングの現在地
- 水平シャーディングへの複数年投資: Figmaの将来的なスケーラビリティのために水平シャーディングへの複数年の投資が必要だと認識し、2023年9月に最初の水平シャーディングテーブルをリリースした。
- フェイルオーバーの成功: データベースプライマリでは一時的に10秒間の部分的な可用性低下があったものの、レプリカには可用性への影響なく、フェイルオーバーを成功裏に達成した。シャーディング後もレイテンシや可用性の面で回帰はなかった。
- 複雑なシャード処理: 最も書き込み率の高いデータベースに対して、比較的単純なシャード処理を行った。今年は数十のテーブルと数千のコード呼び出し箇所を持つ、さらに複雑なデータベースのシャーディングを予定している。
- Figmaの全テーブルに対する水平シャーディングの必要性: 最後のスケーリング限界を取り除き、真の非常時対応力を得るために必要だ。完全に水平シャーディングされた世界は、信頼性向上、コスト削減、開発者速度の向上など、さまざまな利点をもたらす。
- 解決すべき課題:
- 水平シャーディングされたスキーマ更新のサポート
- 水平シャーディングされた主キー向けのグローバルに一意なID生成
- ビジネス上重要なユースケース向けのアトミックなクロスシャードトランザクション
- 分散されたグローバル一意インデックス(現在はシャーディングキーを含むインデックスのみ対応)
- 水平シャーディングとシームレスに互換するORMモデルによる開発者速度の向上
- ボタンクリックでシャード分割を実行できる完全自動化されたリシャード作業
- 既存のRDS水平シャーディングアプローチの再評価: 18か月前、非常にタイトなタイムラインのプレッシャーの中で始まった取り組みだった。NewSQLストアの継続的な進化と成熟もある。現在の路線を維持することと、オープンソースまたはマネージドソリューションへ移行することのトレードオフを再評価するのに十分な余裕が今はある。
- 水平シャーディングの道のりにおける興味深い進展: なお解決すべき課題は多く、その取り組みはまだ始まったばかりだ。水平シャーディングスタックのさまざまな部分について、今後さらに深い分析が期待される。このようなプロジェクトに関心があるなら、連絡してほしい。採用中とのこと。
GN⁺の見解
- Figmaのデータベースチームは、水平シャーディングを通じてデータベースのスケーラビリティ限界を克服しようとしており、これはクラウドベースのコラボレーションツールの成長と性能維持において重要なステップだ。
- 水平シャーディングは、データ管理とクエリ最適化において新たな課題をもたらし、データベース管理者や開発者に新しい知識と技術を求める。
- 水平シャーディングはデータベースのスケーラビリティを大きく向上させる一方で、複雑なクエリ処理やデータ整合性維持のための新たな解決策を必要とする。
- 類似の機能を提供するオープンソースプロジェクトとしてはCitusDBがあり、Postgresデータベースを水平に拡張する機能を提供している。
- 水平シャーディング技術を導入する際には、データモデルの複雑さ、クエリ性能、システムの柔軟性、保守性を考慮する必要があり、これはデータベースのスケーラビリティと運用しやすさのバランスを取ることを意味する。
1件のコメント
Hacker Newsのコメント
大規模テーブルとRDSのIOPS上限
シャーディング後の結果とコスト
シャーディングに要した時間とコスト
YugabyteDBとのコスト比較
顧客ごとのデータベース分離提案
MySQLのVitessに似たPG版の構築
FoundationDBの検討
シャーディングをハックのように扱うアプローチ
Citus拡張を使っていないことへの疑問
Aurora Limitlessの利用可能性
NoSQLデータベースへの理解
シャーディングの成熟度とNewSQLソリューションの検討
GoogleのSpanner技術とFigmaの評価