Shopifyに対して、外部システムから大量/高頻度でデータを同期する際のベストプラクティス
はじめに
多くの企業では、在庫管理システムや商品管理システム(PIM等)などの外部システムを正とし、Shopifyを参照システムとして利用しています。本記事では、こうした環境下で、Shopifyに対して大量または高頻度でデータを同期する際のベストプラクティスをご紹介します。
Shopifyは現在、従来のREST APIを段階的に非推奨(deprecated)とし、GraphQL Admin APIへの移行を推奨しています。GraphQLは柔軟かつ効率的なデータ取得・更新を可能にし、Shopifyのインフラ負荷軽減にもつながるため、今後の開発ではGraphQLベースの設計が前提となるでしょう。
ベストプラクティスの概要
GraphQLを利用する
GraphQLは、必要なデータのみを明示的にリクエストできるため、REST APIのような過剰取得(オーバーフェッチ)を防げます。REST API では、データ取得がリソース単位に分割されているため、関連情報を取得するには複数のエンドポイントを順次呼び出す必要があります。例えば商品に関する情報を取得する場合、まずproducts エンドポイントを呼び出して variant_id を取得し、その後 /variants/{id} といった別のエンドポイントに対して追加のリクエストを発行しなければなりません。
このように、データ構造を段階的に「ドリルダウン」する操作や、テーブルを横断して関連情報を取得する操作は、複数回のリクエストに分かれがちです。一方 GraphQL では、クライアントが必要とするデータの構造をクエリで明示的に定義できます。
そのため、商品情報とそのバリアント情報、さらに関連する在庫や価格といった別テーブル由来のデータを、単一のリクエストで取得可能です。
これにより ネットワーク往復回数の削減、過剰または不足データの排除、効率的なデータ取得 が実現され、パフォーマンスや開発生産性の向上につながります。
ShopifyでもGraphQLでのみ提供されている機能が多く、APIの中心となっています。GraphQLのレート制限について
Shopify GraphQL APIでは、単純なリクエスト回数ではなく、「コスト(複雑さ)」に基づいたレート制限が導入されています。これは、リーキーバケットアルゴリズムに基づき、複雑なクエリはより多くのコストを消費するため、効率的なクエリ設計が重要です。
スロットルの処理
ShopifyのAPIは、リクエストが制限を超えるとHTTP 429(Too Many Requests)や503(Service Unavailable)を返します。これは主に前述のリーキーバケット方式に基づいています。
スロットルされた場合は、即時再試行ではなく、少なくとも1秒以上待ってからリトライするのが推奨されています。
一貫した更新レートを維持する
すべてのデータを定期的にバッチで同期するよりも、変更が発生したタイミングで必要な最小限のデータのみをShopifyに同期する方がパフォーマンスと信頼性が高まります。
推奨例:
商品や在庫の更新は変更イベントが起こる度にShopifyに同期することを推奨します。
非推奨例:
毎日深夜に全商品と在庫の状態をShopifyに同期するなど、定期的に全商品のデータを更新することは、失敗のリスクを高めます。
ストリーミングシステムを利用する
外部システムでのデータ変更に即時対応し、Shopifyへリアルタイムに近い形で同期したい場合は、ストリーミング連携が有効です。たとえばGCPのPub/SubやAWSのSNSなどを用いることで、イベントドリブンなデータ更新が可能になります。
GCPでの例:
- 元データを保持するシステムが更新イベントをPub/Subに送信
- Cloud Run関数がPub/Subからデータを受け取り、Shopify APIへ反映
このような構成により、ランニングコストを抑えつつ、大量の変更にも対応可能な柔軟な仕組みが構築できます。
ShopifyのリソースIDを保管する
Shopifyのリソース(例:商品、バリエーション、在庫)を更新するには、各リソースのIDが必要です。IDが外部システムに保存されていない場合、まず検索でIDを取得し、次に更新する必要があり、APIコールが2回になります。
推奨例:
初回登録時にWebhook等でShopify IDを取得し、外部システム側に保存しておく。
非推奨例:
毎回GraphQLでIDをクエリしてから更新を実行する(二重コール)。
リソース専用のバルクAPIオペレーションを利用する
Shopifyでは、リソースに特化したバルクAPIが提供されており、効率的な一括更新が可能です。
- productVariantsBulkCreate
- productVariantsBulkUpdate
- productVariantsBulkDelete
- inventoryAdjustQuantities
- metaobjectBulkDelete
推奨例:
バリエーションを一括で更新するために、productVariantsBulkUpdateを呼び出す。
非推奨例:
productUpdate操作を使用してbulkOperationRunMutationを呼び出す。
各シナリオでの対応
以下のセクションでは、Shopifyで大量のデータを管理するにあたって、各シナリオで推奨される方法を具体例を交えてご紹介します。
初回データインポート
大量の商品を取り扱う場合は、Admin APIの productCreate mutation を用いて、スクリプトで初回インポートを自動化することをお勧めします。
productCreateを使う場合は、前述のスロットル処理に注意してください。
Shopifyで在庫管理を行うには、すべての商品と在庫ロケーションを作成し、それぞれのリソースIDを保存したうえで、 inventoryActivate によってバリアントの在庫を有効化し、初期の在庫数を設定します。
価格の更新
大量SKUの価格を効率的に更新するには、次のような方法を推奨します。
- 個別のバリアント:productVariantUpdate
- 同一商品の一部バリエーション:productVariantsBulkUpdate
- 大量のバリエーションの作成/削除:productVariantsBulkCreate / productVariantsBulkDelete
注意:
productUpdate を使用すると、指定していない他のバリエーションが削除されるリスクがあります。
在庫の更新
Shopifyの在庫には以下のようなステータスがあります:
- 手持ち
- 販売可能
- 確定済み
- 利用できません
- 入荷中
Shopifyの在庫APIは同期実行です。mutationが返ると同時に在庫数が反映されます。
以下を前提としています:
- Shopify側で在庫トラッキングを有効化している
- 複数ロケーション対応
- ロケーションごとの在庫トラッキング
- 実際に保持している在庫数と一致した更新を行う
推奨方法:
- inventoryAdjustQuantities や inventorySetOnHandQuantities によるバッチ処理
非推奨方法:
- callback_url/fetch_stock や REST API inventory_levels/set.json の使用
在庫の一括更新
在庫更新は1回のAPIコールでまとめて処理するのが理想です。
推奨の方法:
inventoryAdjustQuantities による一括更新
非推奨の方法:
複数の個別APIリクエストで順次更新する
メタフィールドの更新
メタフィールドは、商品、注文、顧客に対してセグメントなどのカスタム情報を追加することのできる機能です。
推奨の方法:
商品または商品バリエーションに新しくメタフィールドを追加する際は、できる限り商品または商品バリエーションオブジェクトの作成時にメタフィールドを同時追加してください。
既存の商品やバリエーションに対してメタフィールドを更新する場合は、metafieldsSetの利用を推奨します。最大25件までの一括更新が可能です。
非推奨の方法:
- productUpdateやproductVariantUpdateをメタフィールドの更新に使用すること
- metafieldsSetを複数回に分けて書く形式
Unset
mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) {
update1: metafieldsSet(metafields: $input1) {
...
}
update2: metafieldsSet(metafields: $input2) {
...
}
update3: metafieldsSet(metafields: $input3) {
...
}
}
代わりに、更新対象をひとつの配列にまとめて、単一のmetafieldsSetで渡してください。
まとめ
- REST APIよりもGraphQLの利用を優先する。
- スロットルされた、または予期しないAPI応答を処理するための戦略を実装する。
- 一貫した更新レートを維持する。
- ShopifyリソースIDを保存してAPIコールを最適化する。
- リソース専用のバルクAPIを活用する。
ShopifyのAPI活用は、運用効率だけでなくビジネスの成長スピードにも大きく影響します。本記事が、よりスケーラブルな構築の一助となれば幸いです。