supabase-realtime
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSupabase Realtime
Supabase Realtime
Expert implementation guide for Supabase Realtime features focusing on scalable patterns and best practices.
一份专注于可扩展模式与最佳实践的Supabase Realtime功能专业实现指南。
Core Principles
核心原则
Always use over - postgres_changes is single-threaded and doesn't scale. Use broadcast with database triggers for all database change notifications.
broadcastpostgres_changesUse dedicated topics - Never broadcast to global topics. Use granular patterns like , .
room:123:messagesuser:456:notificationsPrivate channels by default - Set for all database-triggered channels. Enable private-only mode in production.
private: true优先使用而非——postgres_changes是单线程的,不具备可扩展性。所有数据库变更通知都应结合数据库触发器使用broadcast。
broadcastpostgres_changes使用专用主题——切勿向全局主题广播消息。使用细粒度的命名模式,例如、。
room:123:messagesuser:456:notifications默认使用私有频道——为所有数据库触发的频道设置。在生产环境中启用仅私有模式。
private: trueQuick Reference
快速参考
Naming Conventions
命名规范
- Topics: (e.g.,
scope:entity:id)room:123:messages - Events: in snake_case (e.g.,
entity_action)message_created
- 主题:(例如:
scope:entity:id)room:123:messages - 事件:使用蛇形命名法的(例如:
entity_action)message_created
Client Setup Pattern
客户端设置示例
javascript
const channel = supabase.channel('room:123:messages', {
config: {
broadcast: { self: true, ack: true },
private: true // Required for RLS
}
})
// Set auth before subscribing
await supabase.realtime.setAuth()
channel
.on('broadcast', { event: 'message_created' }, handler)
.subscribe((status, err) => {
if (status === 'SUBSCRIBED') console.log('Connected')
})
// Cleanup
supabase.removeChannel(channel)javascript
const channel = supabase.channel('room:123:messages', {
config: {
broadcast: { self: true, ack: true },
private: true // Required for RLS
}
})
// Set auth before subscribing
await supabase.realtime.setAuth()
channel
.on('broadcast', { event: 'message_created' }, handler)
.subscribe((status, err) => {
if (status === 'SUBSCRIBED') console.log('Connected')
})
// Cleanup
supabase.removeChannel(channel)Database Trigger Pattern
数据库触发器示例
sql
-- Use realtime.broadcast_changes for database events
CREATE OR REPLACE FUNCTION notify_table_changes()
RETURNS TRIGGER AS $$
BEGIN
PERFORM realtime.broadcast_changes(
TG_TABLE_NAME || ':' || COALESCE(NEW.id, OLD.id)::text,
TG_OP,
TG_OP,
TG_TABLE_NAME,
TG_TABLE_SCHEMA,
NEW,
OLD
);
RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE TRIGGER messages_broadcast_trigger
AFTER INSERT OR UPDATE OR DELETE ON messages
FOR EACH ROW EXECUTE FUNCTION notify_table_changes();sql
-- Use realtime.broadcast_changes for database events
CREATE OR REPLACE FUNCTION notify_table_changes()
RETURNS TRIGGER AS $$
BEGIN
PERFORM realtime.broadcast_changes(
TG_TABLE_NAME || ':' || COALESCE(NEW.id, OLD.id)::text,
TG_OP,
TG_OP,
TG_TABLE_NAME,
TG_TABLE_SCHEMA,
NEW,
OLD
);
RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE TRIGGER messages_broadcast_trigger
AFTER INSERT OR UPDATE OR DELETE ON messages
FOR EACH ROW EXECUTE FUNCTION notify_table_changes();RLS Authorization
RLS授权
sql
-- Required for private channels
CREATE POLICY "room_members_can_read" ON realtime.messages
FOR SELECT TO authenticated
USING (
topic LIKE 'room:%' AND
EXISTS (
SELECT 1 FROM room_members
WHERE user_id = auth.uid()
AND room_id = SPLIT_PART(topic, ':', 2)::uuid
)
);
-- Required index for performance
CREATE INDEX idx_room_members_user_room ON room_members(user_id, room_id);sql
-- Required for private channels
CREATE POLICY "room_members_can_read" ON realtime.messages
FOR SELECT TO authenticated
USING (
topic LIKE 'room:%' AND
EXISTS (
SELECT 1 FROM room_members
WHERE user_id = auth.uid()
AND room_id = SPLIT_PART(topic, ':', 2)::uuid
)
);
-- Required index for performance
CREATE INDEX idx_room_members_user_room ON room_members(user_id, room_id);Implementation Checklist
实现检查清单
- ✅ Use not
broadcastpostgres_changes - ✅ Dedicated topics per room/user/entity
- ✅ Set for database triggers
private: true - ✅ Create indexes for all RLS policy columns
- ✅ Include cleanup/unsubscribe logic
- ✅ Check channel state before subscribing
- ✅ Use consistent naming conventions
- ✅ 使用而非
broadcastpostgres_changes - ✅ 为每个房间/用户/实体使用专用主题
- ✅ 为数据库触发器设置
private: true - ✅ 为所有RLS策略列创建索引
- ✅ 包含清理/取消订阅逻辑
- ✅ 订阅前检查频道状态
- ✅ 使用统一的命名规范
Scripts
脚本
- scripts/create_broadcast_trigger.sql - Generic broadcast trigger function
- scripts/migrate_from_postgres_changes.sql - Migration helper script
- scripts/create_broadcast_trigger.sql ——通用广播触发器函数
- scripts/migrate_from_postgres_changes.sql ——迁移辅助脚本
Advanced Topics
进阶主题
- Framework Integration: See references/framework_patterns.md
- Performance Optimization: See references/performance_scaling.md
- Migration Guide: See references/migration_guide.md
- 框架集成:请参阅references/framework_patterns.md
- 性能优化:请参阅references/performance_scaling.md
- 迁移指南:请参阅references/migration_guide.md