Xでこんな投稿を見かけました。(https://x.com/jahirsheikh8/status/2070849696730607695

Backend Interview Question:
One of these API designs scales much better.
Which one are you choosing?

A)
GET /users/profile
GET /users/settings
GET /users/orders

B)
GET /users?type=profile
GET /users?type=settings
GET /users?type=orders

A一択だろと思ったけど、リプライを見ると「Bの方が圧倒的にスケーラブル」と書かれていました。

A派が考えるスケーラビリティ

API設計としてのスケーラビリティです。

  • リソースが分かりやすい
  • レスポンス型が固定
  • OpenAPIを書きやすい
  • SDKを生成しやすい
  • 保守しやすい

例えば

GET /users/profile

を見れば「Profileを取得するAPI」であることが一目で分かります。

新しい機能が増えても

GET /users/security
GET /users/preferences
GET /users/notifications

と自然に追加できます。


B派が考えるスケーラビリティ

一方で投稿者が言っていたのは、インフラ構成の話のようです。

例えば

API Gateway
    │
/users?type=profile
    │
Profile Service

/users?type=settings
    │
Settings Service

というように、入口、Interfaceが1つのままで内部サービスだけ増やせるという考え方。

つまり「エンドポイントを増やさなくても済む」という意味でスケーラブルと言っているようでした。

APIのエンドポイントの設計にインフラの設計の事情を持ち込むべきか

APIは、Application Programming Interfaceの略で、アプリケーション同士がやり取りするためのインターフェースです。

Interfaceである以上、APIの設計はアプリケーションの設計の一部であり、インフラの設計とは独立して考えるべきと思っています。

同じことは

/users/profile
/users/settings
/users/orders

でもできます。

API Gateway
        │
/users/profile  ─▶ Profile Service
/users/settings ─▶ Settings Service
/users/orders   ─▶ Order Service

つまり、サービス分割やスケールアウトはURL設計とは独立した話です。

Aだからスケールできない、Bだからスケールするという話ではありません。

Bで成長したあとは結局GraphQLに落ち着くのではないか

Bの設計を突き詰めると、

GET /users?type=profile

だけでは済まなくなります。

そのうち

GET /users?type=profile,settings

GET /users?type=profile&fields=name,email

のようになっていきます。

これは「何を返すか」をクエリパラメータで指定する設計です。

ここまで来ると、RESTというよりGraphQLの発想に近づいていきます。

GraphQLは

query {
  me {
    profile {
      name
    }
    settings {
      theme
    }
  }
}

のように取得したいデータをクライアントが指定します。

つまり、「返すものをクエリで切り替える」という考え方自体がGraphQL寄りになってくる。

結論

今回の議論で一番面白かったのは、AかBかではなく、「スケーラブル」という言葉の意味がお互い違っていたことでした。

  • API設計としてのスケーラビリティ
  • インフラ構成としてのスケーラビリティ

この2つを混ぜてしまうと議論は噛み合いません。

個人的には、REST APIとして設計するなら、リソースごとに責務とレスポンスを明確に分けるAの方が自然だと感じています。