Supabase Realtime進化!ANDフィルタとカラム選択で転送量削減

Supabase Realtimeを利用してチャットアプリやダッシュボードの共同編集、通知機能を構築している開発者にとって、購読フィルタの柔軟性とデータ転送量の削減は重要なテーマです。

これまでのSupabase Realtime(Postgres Changes)では、フィルタ条件を1つのカラムにしか指定できず、複数条件での絞り込みを行いたい場合は全件を受信してからフロントエンド側で不要なイベントを破棄する必要がありました。また、テーブル更新時にはレコード全体の全カラムがペイロードに含まれるため、通信量が増加しやすいという課題がありました。

今回のアップデートにより、Postgres Changesで複数カラムを組み合わせたANDフィルタ、カラム選択(select)、および like や is などの拡張演算子が正式にサポートされました。

この記事では、新しく追加されたフィルタ機能とカラム選択の具体的な設定手順、実装コード例、そして通信量やコスト削減への影響について詳しく解説します。

この記事で行うこと

  • Postgres Changesの新機能(複数カラムANDフィルタ、カラム選択、新演算子)の概要を把握する
  • カンマ区切りおよび新設された postgresChangesFilter() ビルダー関数を用いた購読コードを実装する
  • select オプションを指定して、必要なカラムのみを受信する設定を行う
  • 通信データ転送量(Egress)やRealtimeメッセージ数の削減効果を理解する
  • アップデート時の注意点や未対応の制限事項を確認する

前提条件・対象読者

  • Supabaseでチャット、ダッシュボード、通知などのリアルタイム機能を開発しているエンジニア
  • Realtimeのデータ転送量(Egress)やメッセージ課金を削減したいプロジェクト担当者
  • Supabaseのアカウントおよびプロジェクトを作成済みであること
  • 対象テーブルのRealtime機能(Publication)が有効化されていること
  • カラム選択機能を利用する場合、クライアントライブラリ @supabase/supabase-js のバージョンが 2.109.0 以上であること
  • Node.js環境(v18以上推奨)またはブラウザ環境でのJavaScript/TypeScript開発環境が整っていること

注意点

新機能を利用するにあたり、以下の制限事項と仕様を事前に把握しておく必要があります。

  • カラム選択には @supabase/supabase-js のバージョン 2.109.0 以上が必要です。古いバージョンでは select オプションが無視され、全カラムが返されます。
  • 今回のリリースでサポートされた複合フィルタは「AND条件」のみです。「OR条件」による結合は現時点で未サポートです。
  • DELETE イベント時は行のPrimary Keyのみが通知されるため、カラムごとの値に基づくフィルタ条件は評価されません。
  • 配列やJSONの包含判定、全文検索、範囲演算子など、PostgRESTの一部高度なクエリ演算子はRealtimeフィルタではまだ利用できません。
  • Row Level Security(RLS)は引き続き適用されます。select で指定したカラムは、購読を行うロールにSELECT権限が付与されている必要があります。

アップデートの概要と旧仕様との比較

これまでの仕様と今回のアップデート内容の違いを整理します。

1. 複数カラムのANDフィルタ対応

従来は1カラムのみの指定(例: status=eq.open)に制限されていたため、特定チームに割り当てられたオープンチケットだけを購読したい場合でも、すべてのオープンチケットを受信してアプリ側で if (payload.new.team_id !== myTeamId) のように間引く必要がありました。 新仕様では、カンマ区切りまたは専用ビルダーにより複数条件をAND結合してサーバー側で正確にフィルタリングできます。

2. カラム選択(select)によるペイロード削減

従来はレコードの変更時に、テーブル内のすべてのカラム値がWebSocket経由で送信されていました。 新仕様では select: ['id', 'title', 'updated_at'] のように必要なカラムだけを指定でき、不要なカラム(大容量のテキストやバイナリ、センシティブなメタデータなど)をサーバー側で除外して受信できます。なお、指定を省略した場合はPrimary Keyのみが常に含まれます。

3. 利用可能な演算子の拡充

従来の単純な一致・比較に加え、パターンマッチの like や ilike、null判定の is、NULL安全な不一致判定 isdistinct、正規表現マッチ match や imatch、そして否定を表す not. 接頭辞が利用可能になりました。

手順1:クライアントライブラリを最新版に更新する

カラム選択オプションを使用するには、@supabase/supabase-js がバージョン 2.109.0 以上である必要があります。プロジェクトのパッケージを最新化します。

npmを使用する場合のコマンドは以下の通りです。

npm install @supabase/supabase-js@latest

package.json でバージョンが 2.109.0 以上になっていることを確認してください。なお、カラム選択を行わずANDフィルタや新演算子のみを利用する場合は、既存バージョンのライブラリのままでも動作します。

手順2:複数カラムのANDフィルタを実装する

複数カラムを条件に指定する場合、文字列によるカンマ区切り形式、または新設されたビルダー関数のいずれかを使用できます。

カンマ区切り文字列で指定する場合

フィルタ文字列の中で条件をカンマ(,)で区切ることで、すべての条件に一致するイベントのみを受信します。

import { createClient } from '@supabase/supabase-js'

const supabase = createClient('https://your-project.supabase.co', 'your-anon-key')

const channel = supabase
  .channel('billing-tickets')
  .on(
    'postgres_changes',
    {
      event: 'UPDATE',
      schema: 'public',
      table: 'tickets',
      filter: 'status=eq.open,team=eq.billing',
    },
    (payload) => {
      console.log('課金チームの未完了チケットが更新されました:', payload)
    }
  )
  .subscribe()

postgresChangesFilterビルダーを使用する場合

型安全性や可読性を重視する場合は、@supabase/supabase-js からインポートできる postgresChangesFilter() ビルダー関数を使用したメソッドチェーン形式が便利です。

import { createClient, postgresChangesFilter } from '@supabase/supabase-js'

const supabase = createClient('https://your-project.supabase.co', 'your-anon-key')

const channel = supabase
  .channel('priority-tickets')
  .on(
    'postgres_changes',
    {
      event: 'INSERT',
      schema: 'public',
      table: 'tickets',
      filter: postgresChangesFilter()
        .eq('status', 'open')
        .gte('priority', 3),
    },
    (payload) => {
      console.log('優先度3以上の新規チケット:', payload)
    }
  )
  .subscribe()

チェーンされた条件はすべてAND条件として結合されます。普段Supabaseのクエリビルダーで書き慣れている記法と近い感覚で購読条件を組み立てられます。

手順3:カラム選択(select)を指定して受信データを絞り込む

画面表示に必要なカラムだけを指定することで、受信するJSONペイロードのサイズを小さく抑えられます。

import { createClient } from '@supabase/supabase-js'

const supabase = createClient('https://your-project.supabase.co', 'your-anon-key')

const channel = supabase
  .channel('ticket-list-summary')
  .on(
    'postgres_changes',
    {
      event: '*',
      schema: 'public',
      table: 'tickets',
      filter: 'status=not.eq.archived',
      select: ['id', 'subject', 'updated_at'],
    },
    (payload) => {
      console.log('チケット要約ペイロード:', payload.new)
      // payload.new には id, subject, updated_at のみが含まれます
    }
  )
  .subscribe()

既存の購読コードに対して select オプションを追加しない限りは、従来通りレコード全体の全カラムが届くため、既存の実装を壊さずに段階的に導入できます。

手順4:新しく追加された演算子を活用する

文字列の部分一致やnullチェック、否定条件など、これまで対応していなかった条件指定を試してみましょう。

import { createClient } from '@supabase/supabase-js'

const supabase = createClient('https://your-project.supabase.co', 'your-anon-key')

// 特定ドメインのメールアドレスに限定(like)
const userChannel = supabase
  .channel('company-users')
  .on(
    'postgres_changes',
    {
      event: 'INSERT',
      schema: 'public',
      table: 'users',
      filter: 'email=like.%@example.com',
    },
    (payload) => console.log('社内ユーザー登録:', payload)
  )
  .subscribe()

// 論理削除されていないレコードに限定(is.null)
const activeRecords = supabase
  .channel('active-items')
  .on(
    'postgres_changes',
    {
      event: 'UPDATE',
      schema: 'public',
      table: 'items',
      filter: 'deleted_at=is.null',
    },
    (payload) => console.log('有効アイテム更新:', payload)
  )
  .subscribe()

// 特定ステータス以外を除外(not.eq)
const inProgressTasks = supabase
  .channel('tasks')
  .on(
    'postgres_changes',
    {
      event: 'UPDATE',
      schema: 'public',
      table: 'tasks',
      filter: 'status=not.eq.archived',
    },
    (payload) => console.log('アーカイブ以外のタスク更新:', payload)
  )
  .subscribe()

通信量とコストへの好影響

Supabase Realtimeは、送信されたメッセージ数およびEgress(アウトバウンドデータ転送量)に基づいて課金が計算されます。

データベースで1行が更新された際、そのテーブルを購読しているクライアントの数だけメッセージが配信されます。 サーバー側のANDフィルタによって不要なイベントが拒否されると、クライアントへの配信メッセージ数が減少し、Realtimeのメッセージクォータ消費を直接抑制できます。

さらに、select オプションで不要なカラム(本文データやログ情報など)を削ることで、1メッセージあたりのデータサイズが小さくなり、Egress転送量の削減に繋がります。高トラフィックなサービスやモバイルアプリにおいて、通信コストと端末バッテリー消費の両面で大きなメリットとなります。

うまくいかない場合の確認ポイント

設定後にイベントが届かない、または想定外のデータが届く場合は以下を確認してください。

  • ライブラリのバージョンが古い: カラム選択が効かず全カラムが届いてしまう場合、npm list @supabase/supabase-js を実行してバージョンが 2.109.0 未満になっていないか確認してください。
  • テーブルのPublication設定: Supabaseダッシュボードの「Database」→「Replication」で、対象テーブルのRealtime(supabase_realtime)が有効になっているか確認してください。
  • RLSポリシーの制限: Row Level Security(RLS)が有効なテーブルでは、購読者が対象行に対するSELECT権限を持っていないとイベントが配信されません。anonキーや認証トークンの権限設計を確認してください。
  • DELETEイベント時の挙動: 削除イベントは行のPrimary Keyしか持たないため、通常カラムに対するフィルタ(例: status=eq.open)を設定していると、DELETE イベントはフィルタに合致せず破棄されます。

よくある質問

Q. OR条件(いずれかの条件に一致)は使えますか? A. 今回のリリースではAND条件のみがサポートされています。OR条件による購読を行いたい場合は、別々のチャンネルとして購読するか、従来通りアプリ側で判定する必要があります。

Q. 既存の購読コードは書き直す必要がありますか? A. いいえ、既存のコードはそのまま動作し続けます。ANDフィルタやカラム選択を明示的に指定したチャンネルのみ挙動が変更されます。

Q. カラム選択にPrimary Keyを含めなかった場合はどうなりますか? A. select 配列にPrimary Keyを含め忘れた場合でも、レコードを識別するためにPrimary Keyは自動的にペイロードへ含まれます。

まとめ

Supabase RealtimeのPostgres Changesに追加された新機能により、リアルタイムイベントの購読精度が向上し、無駄なメッセージ送信とデータ転送量を大幅に削減できるようになりました。

  • カンマ区切りまたは postgresChangesFilter() により複数カラムのANDフィルタが可能
  • select オプションで必要なカラムのみを安全かつ軽量に受信
  • likeisisdistinctnot. などの演算子で柔軟な絞り込み
  • サーバー側での除外により、Realtimeメッセージ課金とEgressコストを低減

リアルタイム通信のコストやモバイル端末の負荷に悩んでいたプロジェクトは、ぜひ @supabase/supabase-js を更新して導入してみてください。

次に読むおすすめ記事

【2026年9月】Supabase新機能まとめ|Realtime大幅改善とMCP強化
オープンソースのFirebase代替として進化を続けるBaaS(Backend as a Service)「Supabase」より、2026年9月の大型アップデート情報が公開されました。今月のアップデートは、個人開発者からエンタープライズ企…

参考情報