Convex入門 第1回 Convexを使ってみる

Convexは、リアルタイム更新を前提に設計された、比較的新しいBaaSです。本記事では、FirebaseやSupabaseと比較しながら、Convexがどのようなサービスかを紹介します。

発行

著者 中野 祐人 モダンフロントエンド・エンジニア
Convex入門 シリーズの記事一覧

Convexとは?

Convexは、2023年に登場した比較的新しいバックエンドサービス、いわゆるBaaS(Backend as a Service)です。

BaaS

BaaSとは、データベースや認証、プッシュ通知など、アプリ開発に必要なサーバーサイド機能をパッケージ化し、APIやSDKとして提供する仕組み。

データの取得方法には、大きく2つの考え方があります。ひとつは「必要なときにサーバーへ問い合わせ、結果を受け取る」リクエスト/レスポンスモデル。もうひとつは「データが変化したらサーバーから新しいデータが自動でプッシュされる」リアクティブなサブスクリプションモデルです。FirebaseやSupabaseを含む多くのサービスは前者を基本としており、リアルタイム更新は追加するオプション扱いになっています。一方でConvexはすべてのデータを自動的にリアルタイムに更新するようになっているサービスです。

具体的なシーンで考えてみましょう。記事を編集するアプリで、記事一覧ページと記事詳細ページがある場合を想像してください。詳細ページで記事のタイトルを編集して保存したとき、リクエスト/レスポンスモデルを基本とする構成では、編集した際に一覧ページを開いている別のユーザーの画面に変更は届きません。そのユーザーがページをリロードしてはじめて新しいタイトルが表示されます。これは当たり前のことのように感じるかもしれませんが、Convexでは違います。

Convexは最初からサブスクリプションモデルを前提に設計されており、どのユーザーが一覧ページを開いていても、タイトルが保存された瞬間に自動で画面が更新されます。これはチャットのような明らかにリアルタイム性が必要なアプリだけでなく、CMSの管理画面やタスク管理ツールのようなアプリでも同じです。

「なるほど、すべてが自動で更新されるとして、それが本当にうれしいのか?」と感じる方もいるかもしれません。実は筆者もConvexを使う前は同じように「チャットサービスのような明確にリアルタイムが必要な場面ならともかく、データの閲覧・作成・編集・削除ができればよいアプリにそこまでするのは過剰なのではないか」と思っていました。

しかし実際に使ってみると、リアルタイム更新の本当の価値はユーザー体験だけでなく、開発体験にこそあると気づきました。リアルタイムに更新されることで、「データをどのタイミングで再取得するか」「更新後にキャッシュをどう扱うか」を全く気にせずに開発できるのです。データが変われば画面も変わる、ただそれだけのシンプルな前提で実装できることがConvexの一番の特徴です。

第一回目では、Convexがどのようなサービスかを知ってもらうために、代表的なバックエンドサービスとの比較とリアルタイムチャットの実装例を紹介します。

代表的なバックエンドサービスと比較

まずはConvexの特徴を、先行のBaaSであるFirebaseSupabaseとの違いを例として、説明します。

vs Firebase

Convexはリアルタイムのデータ更新をサポートしていますが、これはFirebase Realtime Databaseに近い部分があります。

Firebase Realtime Databaseは、複数ノードをまたいだ更新を厳密に扱おうとすると、アプリケーション側での設計や運用の工夫が必要になるケースがあります。実例として、筆者が過去に関わった案件では、こうした複雑さを避けるために、バックエンド側でのトランザクション的な処理を諦め、エラーが発生した場合は通知し、その後手動で修正する、という運用方針を取っていました。その点、Convexでは、トランザクションがネイティブにサポートされており、特別な設計や運用を意識することなく、データの整合性を担保できます。

FirebaseのCloud Firestoreも、リアルタイム更新やトランザクションには対応しています。しかし、変更を受け取るための処理や状態管理のコードを自分で書く必要があります。一方Convexは、リアルタイム更新がデフォルトで組み込まれており、Convexのクライアントライブラリを使うだけで自動的にその恩恵を受けられます。この「書かなくていい」という差が、開発体験の違いとして大きく効いてきます。

vs Supabase

SupabaseはPostgreSQLをベースにしているので、細かいアクセス制御や複雑な条件でのデータ取得など、リレーショナルデータベースならではの強力な機能を持っています。

そのほか、Supabaseには認証機能がありますが、Convexではまだbeta段階で、基本的に他の認証サービスと組み合わせて使用することになります。

逆にSupabaseはリアルタイム更新のためには追加設定が必要ですが、Convexはネイティブサポートしています。

筆者の印象ですが、SupabaseはSQLの記述やマイグレーション管理、スキーマ設計や権限管理を含めて、アプリケーション全体を腰を据えて設計することが前提のバックエンドサービスだと感じました。

実際に使ってみると、ローカルとリモートのマイグレーションの同期や管理、細かなアクセス制御をきちんと設定や運用をすれば強力ではあるものの、考慮すべきことが多く1つの機能を開発するのにたくさんのことをしなければならない印象です。

一方でConvexは、TypeScriptの型でスキーマを管理でき、convexクライアントライブラリがリアルタイム性を担保して状態管理を含めた部分を引き受けてくれるため、少ない実装量でよいUXのアプリケーションを立ち上げられるバックエンドサービスだと感じています。

料金体系

Convexの料金体系は、執筆時点(2026年2月)ではFreeプラン、従量課金のStarterプラン、開発者一人につき$25のProプランがあります。

開発開始からリリース、本番運用までを考えても、Freeプランで始め、局所的に制限をオーバーするようになったらStarterプランにアップグレード、さらにユーザーが増え、従量課金が損になりそうなタイミングでProプランに移行する、という流れで十分な印象です。

プランごとの制約で気になる点は、FreeプランとStarterプランではカスタムドメインが使用できないこと。カスタムドメインを使用したい人は、Proプランを選ぶ必要があります。

用途によるのであくまでも個人的な印象ですが、ドキュメント数やリクエスト数にはFreeプランでもかなり余裕があります。しかし、Freeプランのデータベースの帯域幅1GB/月は厳しく、そのあたりの制限で従量課金に移行することになるかなと思います。

少しコードを見てみましょう

では、Convexの使用感がどんなものか、実装で少し見てみましょう。

次のようなリアルタイムチャットを実装する場合を見てみます。右と左のウィンドウは別のユーザーで、片方に送ったメッセージは即時もう片方にリアルタイムに反映される、というイメージです。

これをconvex-svelteライブラリを使って、Svelteに実装したコードは次のようになります。

リアルタイムチャットアプリのフロントエンド

<script lang="ts">
  import { useQuery, useConvexClient } from "convex-svelte";
  import { api } from "../convex/_generated/api.js";

  const client = useConvexClient();

  // リアルタイムにメッセージを購読
  const messages = useQuery(api.messages.list, {});

  let author = $state("");
  let body = $state("");

  function send() {
    client.mutation(api.messages.send, { author, body });
    body = "";
  }
</script>

<!-- メッセージ表示 -->
{#each messages.data ?? [] as message (message._id)}
  <div class="chat {message.author === author ? 'chat-end' : 'chat-start'}">
    <div class="chat-header">{message.author}</div>
    <div class="chat-bubble">{message.body}</div>
  </div>
{/each}

<!-- メッセージ送信フォーム -->
<form onsubmit={send}>
  <input bind:value={author} placeholder="Your name" />
  <input bind:value={body} placeholder="Message" />
  <button>Send</button>
</form>

ポイントは、convex-svelteライブラリから呼び出しているuseQueryを用いて、メッセージ取得のコードを書くだけで、他のクライアントからの変更がリアルタイムに反映される点です。

またconvex/_generated配下からapiをインポートしていますが、これはConvexが自動生成してくれる型定義済みのAPIコードであり、サーバー側で定義した関数を型安全に呼び出しています。

どうでしょうか、スタイルやエラー処理を省いているものの、たったこれだけのコードで、リアルタイムに更新されるチャットアプリが実装されるのはなかなか驚きではないでしょうか。

この例ではSvelteを使用しましたが、もちろんReactをはじめ、主要なフレームワークに対応した、同様の書き味のクライアントライブラリがあります。

くわしくは、convexのドキュメントを参照してください。

まとめ

今回はConvexについて、他のサービスとの比較を交えながら紹介しました。

筆者は個人でもサービス開発を行っており、これからはConvexを使用していこうと思っています。

以前はSupabaseを使用していたのですが、Convexのほうが自身で考えなければならないことが少なく、開発生産性が高いと感じます。

ぜひ皆さんも試してみてください。

次回は開発環境の構築や、バックエンド部分も含めたデータの取得部分について詳しく見ていきたいと思います。