How to fix REALTIME_TIMEOUT: Connection to Realtime server timed out in Supabase

SupabaseINTERMEDIATEMEDIUMUpdated Dec 22, 2025· 216 views

The "REALTIME_TIMEOUT: Connection to Realtime server timed out" error occurs when Supabase Realtime cannot establish or maintain a WebSocket connection to the realtime server. This typically happens due to network issues, firewall restrictions, browser extensions, or server-side configuration problems. The error prevents realtime features like live subscriptions, presence, and broadcast channels from working.

Quick fix

Fixes REALTIME_TIMEOUT: Connection to Realtime server timed out

# Test WebSocket connectivity using wscat
   npm install -g wscat
   wscat -c "wss://YOUR_PROJECT_REF.supabase.co/realtime/v1"

   # Alternative using curl for WebSocket handshake test
   curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: YOUR_PROJECT_REF.supabase.co" -H "Origin: https://YOUR_PROJECT_REF.supabase.co" https://YOUR_PROJECT_REF.supabase.co/realtime/v1
  1. Check browser extensions and network settings
  2. Verify Supabase project configuration
  3. Configure firewall and network settings
  4. Implement connection timeout handling and retries
supabase — error
# Test WebSocket connectivity using wscat
npm install -g wscat
wscat -c "wss://YOUR_PROJECT_REF.supabase.co/realtime/v1"
# Alternative using curl for WebSocket handshake test
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: YOUR_PROJECT_REF.supabase.co" -H "Origin: https://YOUR_PROJECT_REF.supabase.co" https://YOUR_PROJECT_REF.supabase.co/realtime/v1
REALTIME_TIMEOUT: Connection to Realtime server timed out

What this error means

The "REALTIME_TIMEOUT: Connection to Realtime server timed out" error is a Supabase Realtime error that indicates the client cannot establish a WebSocket connection to Supabase's realtime server within the expected timeframe. Supabase Realtime is built on PostgreSQL's logical replication and WebSockets, allowing real-time updates from your database. When you subscribe to changes (using `supabase.channel()` and `.on()`), the client attempts to connect to `wss://<project-ref>.supabase.co/realtime/v1` via WebSocket. This timeout error typically occurs when: 1. **Network connectivity issues** - Firewalls, proxies, or network restrictions blocking WebSocket connections 2. **Browser/extension interference** - Ad blockers, privacy extensions, or browser settings preventing WebSocket connections 3. **Server-side configuration** - CORS issues, incorrect project configuration, or regional server problems 4. **Client-side issues** - Incorrect initialization, missing authentication, or library version mismatches 5. **Infrastructure limits** - Free tier limitations or rate limiting on realtime connections The error is particularly common in development environments, corporate networks with strict security policies, or when using certain browser extensions that interfere with WebSocket connections.

Typical symptoms

  • Supabase Realtime subscriptions fail with "REALTIME_TIMEOUT: Connection to Realtime server timed out" error
  • WebSocket connection attempts hang or timeout after 30-60 seconds
  • Realtime features (live updates, presence, broadcast) do not work
  • Error occurs in browser console or server logs when initializing Supabase client
  • Connection works intermittently or fails consistently
  • Other Supabase features (database queries, auth) work fine, but realtime fails
  • Error may appear during development but work in production (or vice versa)
  • Browser network tab shows WebSocket connection attempts failing or timing out

Common causes

  1. Firewall or network security policies blocking WebSocket connections (ports 443/wss)
  2. Corporate proxy servers interfering with WebSocket handshake
  3. Browser extensions (ad blockers, privacy tools) blocking WebSocket connections
  4. Incorrect CORS configuration in Supabase project settings
  5. Missing or incorrect Supabase project URL or anon key
  6. Network latency or packet loss causing WebSocket timeout
  7. Supabase Realtime server regional issues or maintenance
  8. Free tier limitations on concurrent realtime connections
  9. Client-side WebSocket implementation issues or library bugs
  10. DNS resolution problems for realtime server hostname
  11. SSL/TLS certificate validation failures
  12. Browser security settings preventing cross-origin WebSocket connections

How to fix "REALTIME_TIMEOUT: Connection to Realtime server timed out"

1Check browser extensions and network settings

First, eliminate common browser and network issues:

1. Disable browser extensions:
- Temporarily disable ad blockers (uBlock Origin, AdBlock Plus)
- Disable privacy extensions (Privacy Badger, Ghostery)
- Turn off security extensions that might block WebSockets
- Test in incognito/private mode (extensions are usually disabled)

2. Check network connectivity:

bash
# Test WebSocket connectivity using wscat
   npm install -g wscat
   wscat -c "wss://YOUR_PROJECT_REF.supabase.co/realtime/v1"

   # Alternative using curl for WebSocket handshake test
   curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: YOUR_PROJECT_REF.supabase.co" -H "Origin: https://YOUR_PROJECT_REF.supabase.co" https://YOUR_PROJECT_REF.supabase.co/realtime/v1

3. Test from different networks:
- Try from home network vs corporate network
- Test with mobile hotspot
- Check if VPN is interfering

4. Verify WebSocket support in browser:

javascript
// Check if WebSocket is supported
   if (window.WebSocket) {
     console.log('WebSocket supported');
   } else {
     console.error('WebSocket not supported - use a modern browser');
   }

   // Test basic WebSocket connection
   const testSocket = new WebSocket('wss://echo.websocket.org');
   testSocket.onopen = () => console.log('Test WebSocket connected');
   testSocket.onerror = (e) => console.error('Test WebSocket error:', e);
2Verify Supabase project configuration

Ensure your Supabase project is properly configured for Realtime:

1. Check project URL and keys:

javascript
// Correct initialization
   import { createClient } from '@supabase/supabase-js'

   const supabaseUrl = 'https://YOUR_PROJECT_REF.supabase.co'
   const supabaseKey = 'YOUR_ANON_KEY' // Not service role key for client-side

   const supabase = createClient(supabaseUrl, supabaseKey, {
     realtime: {
       params: {
         eventsPerSecond: 10 // Adjust based on needs
       }
     }
   })

2. Enable Realtime for your tables:
- Go to Supabase Dashboard → Database → Replication
- Click "Enable Realtime" for tables you want to subscribe to
- Or use SQL:

sql
-- Enable Realtime for a specific table
   alter publication supabase_realtime add table your_table_name;

   -- Enable Realtime for all tables (not recommended for production)
   alter publication supabase_realtime add table all_tables;

   -- Check which tables have Realtime enabled
   select * from pg_publication_tables where pubname = 'supabase_realtime';

3. Configure CORS settings:
- Go to Supabase Dashboard → Settings → API
- Add your application domains to "Site URL" and "Additional Redirect URLs"
- For development: add http://localhost:3000, http://localhost:5173, etc.
- For production: add your production domain
- Save changes and wait a few minutes for propagation

4. Check project region:
- Go to Supabase Dashboard → Settings → General
- Note your project region
- Ensure it matches where most users are located
- Consider migrating if region is causing latency issues

3Configure firewall and network settings

Adjust network settings to allow WebSocket connections:

1. Allow WebSocket ports:
- WebSocket over TLS (wss) uses port 443 (same as HTTPS)
- Ensure outbound traffic to *.supabase.co:443 is allowed
- For corporate firewalls, whitelist:
- *.supabase.co
- Ports: 443 (HTTPS/wss)

2. Configure proxy settings if needed:

javascript
// If behind a corporate proxy, you may need to configure it
   // Note: Most browsers use system proxy settings automatically

   // For Node.js environments, you might need:
   const { createClient } = require('@supabase/supabase-js');
   const { HttpsProxyAgent } = require('https-proxy-agent');

   const proxyAgent = new HttpsProxyAgent('http://proxy.company.com:8080');

   const supabase = createClient(supabaseUrl, supabaseKey, {
     global: {
       fetch: (url, options) => {
         return fetch(url, {
           ...options,
           agent: proxyAgent
         });
       }
     }
   });

3. Test network connectivity:

bash
# Test DNS resolution
   nslookup YOUR_PROJECT_REF.supabase.co

   # Test HTTPS connectivity
   curl -I https://YOUR_PROJECT_REF.supabase.co

   # Test WebSocket endpoint specifically
   curl -i -N      -H "Connection: Upgrade"      -H "Upgrade: websocket"      -H "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ=="      -H "Sec-WebSocket-Version: 13"      https://YOUR_PROJECT_REF.supabase.co/realtime/v1

4. Check for SSL/TLS issues:
- Ensure system clock is correct (SSL certificates depend on accurate time)
- Update root certificates if needed
- Try disabling SSL verification temporarily for testing (not for production):

javascript
// WARNING: Only for testing in development
   process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
4Implement connection timeout handling and retries

Add robust error handling and retry logic:

1. Implement exponential backoff for reconnections:

javascript
class RealtimeConnection {
     constructor(supabase, channelName, options = {}) {
       this.supabase = supabase;
       this.channelName = channelName;
       this.maxRetries = options.maxRetries || 5;
       this.retryCount = 0;
       this.channel = null;
     }

     async connect() {
       try {
         this.channel = this.supabase.channel(this.channelName);

         // Subscribe to events
         this.channel
           .on('broadcast', { event: 'test' }, (payload) => {
             console.log('Received:', payload);
           })
           .subscribe((status) => {
             if (status === 'SUBSCRIBED') {
               console.log('Connected to Realtime');
               this.retryCount = 0; // Reset on success
             } else if (status === 'CHANNEL_ERROR') {
               this.handleError();
             } else if (status === 'TIMED_OUT') {
               this.handleTimeout();
             }
           });

       } catch (error) {
         this.handleError(error);
       }
     }

     handleError(error) {
       console.error('Realtime error:', error);

       if (this.retryCount < this.maxRetries) {
         const delay = Math.pow(2, this.retryCount) * 1000; // 1s, 2s, 4s, 8s, 16s
         this.retryCount++;

         console.log(`Retrying in ${delay}ms (attempt ${this.retryCount}/${this.maxRetries})`);

         setTimeout(() => {
           this.connect();
         }, delay);
       } else {
         console.error('Max retries reached. Giving up.');
         // Implement fallback logic or notify user
       }
     }

     handleTimeout() {
       console.log('Realtime connection timed out');
       this.handleError(new Error('Connection timeout'));
     }
   }

2. Add connection state monitoring:

javascript
// Monitor connection state
   const channel = supabase.channel('room1');

   channel.on('system', { event: 'disconnect' }, () => {
     console.log('Disconnected from Realtime');
     // Attempt reconnection
   });

   channel.on('system', { event: 'reconnect' }, () => {
     console.log('Reconnected to Realtime');
   });

   channel.subscribe((status) => {
     console.log('Channel status:', status);

     switch(status) {
       case 'SUBSCRIBED':
         console.log('Successfully subscribed');
         break;
       case 'CHANNEL_ERROR':
         console.error('Channel error occurred');
         break;
       case 'TIMED_OUT':
         console.error('Connection timed out');
         break;
       case 'CLOSED':
         console.log('Channel closed');
         break;
     }
   });

3. Implement heartbeat/ping mechanism:

javascript
// Send periodic pings to keep connection alive
   let heartbeatInterval;

   channel.subscribe((status) => {
     if (status === 'SUBSCRIBED') {
       // Start heartbeat
       heartbeatInterval = setInterval(() => {
         channel.send({
           type: 'broadcast',
           event: 'heartbeat',
           payload: { timestamp: Date.now() }
         });
       }, 30000); // Every 30 seconds
     } else if (status === 'CLOSED' || status === 'CHANNEL_ERROR') {
       // Clear heartbeat
       clearInterval(heartbeatInterval);
     }
   });
5Upgrade plan or optimize for Free tier limits

If you're on Free tier, consider these optimizations or upgrades:

1. Free tier limitations:
- 2 concurrent realtime connections per project
- 500 MB database space
- Limited to 1-day log retention

Check if you're hitting limits:

sql
-- Check active Realtime connections
   SELECT count(*) as active_connections
   FROM pg_stat_activity
   WHERE application_name LIKE '%supabase_realtime%';

2. Optimize connection usage:

javascript
// Share channels instead of creating new ones
   const sharedChannel = supabase.channel('shared-channel');

   // Multiple components can listen to the same channel
   sharedChannel.on('postgres_changes', {
     event: 'INSERT',
     schema: 'public',
     table: 'messages'
   }, (payload) => {
     // Update all components listening for new messages
   });

   // Instead of:
   // const channel1 = supabase.channel('comp1');
   // const channel2 = supabase.channel('comp2');
   // const channel3 = supabase.channel('comp3');

3. Implement connection pooling on client side:

javascript
class ConnectionPool {
     constructor() {
       this.connections = new Map();
     }

     getChannel(name) {
       if (!this.connections.has(name)) {
         const channel = supabase.channel(name);
         this.connections.set(name, channel);
       }
       return this.connections.get(name);
     }

     cleanup() {
       this.connections.forEach((channel, name) => {
         if (channel.subscription) {
           supabase.removeChannel(channel);
         }
       });
       this.connections.clear();
     }
   }

4. Consider upgrading to Pro tier:
- $25/month: Unlimited realtime connections
- 8 GB database + 100 GB bandwidth
- 7-day log retention
- Better support and reliability

Upgrade in Supabase Dashboard → Billing

6Debug with Supabase tools and community resources

Use Supabase's debugging tools and community resources:

1. Enable debug logging:

javascript
// Enable verbose logging
   const supabase = createClient(supabaseUrl, supabaseKey, {
     auth: {
       persistSession: true,
       autoRefreshToken: true,
     },
     realtime: {
       params: {
         eventsPerSecond: 10,
       },
       logLevel: 'debug' // Enable debug logging
     }
   });

2. Check Supabase status and community:
- Visit [status.supabase.com](https://status.supabase.com) for platform status
- Check [github.com/supabase/realtime](https://github.com/supabase/realtime) for issues
- Search [supabase.com/docs](https://supabase.com/docs) for Realtime documentation
- Join [supabase.com/discord](https://supabase.com/discord) for community support

3. Test with different clients:

bash
# Test with simple WebSocket client
   # Install: npm install -g wscat
   wscat -c "wss://YOUR_PROJECT_REF.supabase.co/realtime/v1" -H "Authorization: Bearer YOUR_ANON_KEY"

   # Send a test message
   {"topic":"realtime:public:messages","event":"phx_join","payload":{},"ref":"1"}

4. Create minimal reproduction:

html
<!-- Minimal test HTML file -->
   <!DOCTYPE html>
   <html>
   <head>
     <script src="https://unpkg.com/@supabase/supabase-js@2"></script>
   </head>
   <body>
     <script>
       const supabaseUrl = 'https://YOUR_PROJECT_REF.supabase.co';
       const supabaseKey = 'YOUR_ANON_KEY';

       const supabase = window.supabase.createClient(supabaseUrl, supabaseKey);

       const channel = supabase.channel('test-channel');

       channel.subscribe((status) => {
         console.log('Status:', status);
         document.body.innerHTML += `<p>Status: ${status}</p>`;
       });

       setTimeout(() => {
         supabase.removeChannel(channel);
       }, 10000);
     </script>
   </body>
   </html>

5. Contact Supabase support:
- For Pro/Enterprise: Use dashboard support
- Include: error logs, reproduction steps, network traces
- Specify: browser/OS version, network environment, error frequency

Advanced notes

## Understanding Supabase Realtime Architecture

Supabase Realtime uses a combination of technologies:

1. PostgreSQL Logical Replication: Captures database changes
2. Phoenix/Elixir Channels: Manages WebSocket connections
3. PostgreSQL Publication/Subscription: Controls which tables emit changes

### Connection Flow:
1. Client → WebSocket handshake → Realtime Server (Phoenix)
2. Realtime Server → PostgreSQL LISTEN/NOTIFY for presence/broadcast
3. PostgreSQL Logical Replication → Realtime Server → Client

### Timeout Configuration

Default timeouts in @supabase/realtime-js:
- Connection timeout: 30 seconds
- Heartbeat interval: 30 seconds
- Reconnect attempts: 5 with exponential backoff

### Common Pitfalls

1. CORS Preflight Issues:
- WebSocket doesn't use CORS preflight, but initial HTTP handshake might
- Ensure OPTIONS requests are allowed to realtime endpoint

2. WebSocket Subprotocols:
- Supabase uses Phoenix protocol over WebSocket
- Some proxies may strip or modify WebSocket headers

3. SSL/TLS Inspection:
- Corporate SSL inspection can break WebSocket connections
- Try adding certificate to trusted store

4. IPv6 vs IPv4:
- Some networks have IPv6 issues
- Supabase supports both, but network configuration matters

### Performance Considerations

1. Connection Pooling:
- Each browser tab creates separate WebSocket connection
- Consider shared workers for multiple tabs

2. Message Size:
- Large payloads can cause timeouts
- Use eventsPerSecond to limit frequency

3. Subscription Management:
- Unsubscribe from channels when not needed
- Use supabase.removeChannel() to clean up

### Monitoring and Metrics

Key metrics to monitor:
- WebSocket connection success rate
- Message delivery latency
- Reconnection frequency
- Error rate by error type

### Fallback Strategies

When Realtime fails:
1. Polling fallback: Switch to periodic fetch requests
2. Local storage: Cache data locally when disconnected
3. Queue system: Queue updates for when connection restores
4. Offline-first: Design app to work without realtime

### Security Considerations

1. Authentication:
- Use RLS policies for database access control
- Validate JWT tokens on server for sensitive operations

2. Rate Limiting:
- Implement client-side rate limiting
- Use Supabase's built-in rate limiting

3. Data Validation:
- Validate all realtime messages on server
- Sanitize broadcast payloads

Frequently asked questions

What does "REALTIME_TIMEOUT: Connection to Realtime server timed out" mean?
The "REALTIME_TIMEOUT: Connection to Realtime server timed out" error is a Supabase Realtime error that indicates the client cannot establish a WebSocket connection to Supabase's realtime server within the expected timeframe. Supabase Realtime is built on PostgreSQL's logical replication and WebSockets, allowing real-time updates from your database. co/realtime/v1 via WebSocket.
How do I fix "REALTIME_TIMEOUT: Connection to Realtime server timed out"?
The "REALTIME_TIMEOUT: Connection to Realtime server timed out" error occurs when Supabase Realtime cannot establish or maintain a WebSocket connection to the realtime server. This typically happens due to network issues, firewall restrictions, browser extensions, or server-side configuration problems. The error prevents realtime features like live subscriptions, presence, and broadcast channels from working.
What causes "REALTIME_TIMEOUT: Connection to Realtime server timed out"?
Firewall or network security policies blocking WebSocket connections (ports 443/wss) Corporate proxy servers interfering with WebSocket handshake Browser extensions (ad blockers, privacy tools) blocking WebSocket connections
Is the "REALTIME_TIMEOUT: Connection to Realtime server timed out" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading