|

WebSockets en Vercel: por qué no proxear audio en vivo

En pocas palabras: No, porque un WebSocket en Vercel queda fijado a una función serverless con duración máxima, lo que corta la sesión de audio con cold starts y timeouts. TranscribeChirp documentó en Dev.to su solución: usar Vercel solo para auth y créditos, y conectar el navegador directo a Deepgram para el streaming.

El equipo detrás de TranscribeChirp probó poner el WebSocket de audio en vivo directo en una API route de Next.js sobre Vercel, pero ese camino falla en serverless. La solución que documentaron en un posteo técnico en Dev.to: usar WebSockets en Vercel solo para auth y créditos, y conectar el navegador directo a Deepgram para el audio.

Un WebSocket en Vercel es una conexión bidireccional persistente que las Vercel Functions pueden servir en beta pública, pensada para chat, streaming de IA o apps colaborativas. Según la documentación oficial de Vercel, cada conexión queda fijada a una instancia de función y depende de Fluid Compute, algo que la diferencia de un proxy de audio en vivo que necesita sesiones largas y estables.

Resumen rápido

  • TranscribeChirp descartó proxear audio en vivo por Vercel: cold starts a mitad de sesión, timeout duro, facturación rara por keep-alives y riesgo de exponer API keys.
  • Vercel anunció WebSockets nativos en beta pública según su changelog oficial de junio 2026, pero la conexión sigue atada a la duración máxima de la función y requiere Fluid Compute.
  • El patrón recomendado: Vercel como plano de control (auth, créditos, jobs) y el proveedor ASR como plano de datos, con el browser conectado directo a Deepgram.
  • El endpoint de sesión devuelve un token corto (jobId, token, expiresAt) y nunca la master API key.
  • La facturación usa floor en los ticks intermedios y ceil en el minuto final, con la base de datos como fuente de verdad.

¿Qué falla al conectar un WebSocket de audio directamente en una función serverless de Vercel?

Fallan cuatro cosas concretas cuando terminás el socket de audio en una función serverless: cold starts a mitad de sesión, límites duros de tiempo de ejecución, facturación incómoda por conexiones idle y un lugar más donde tus API keys pueden filtrarse en conexiones de larga duración.

Si la función se recicla en medio de una sesión de audio en vivo, la conexión se corta y la transcripción se interrumpe. El equipo de TranscribeChirp lo resume así en su publicación: Vercel y plataformas similares quieren request → response, mientras que un stream de mic en vivo son minutos de bytes bidireccionales.

  • Cold starts mid-session: la función puede reiniciarse mientras el socket sigue abierto, cortando el stream sin aviso.
  • Límites duros de ejecución: cada función tiene un tope de duración configurado, y un audio en vivo largo lo supera fácil.
  • Facturación de keep-alives: cobrar por conexiones idle esperando bytes es un modelo raro para el proveedor y para vos.
  • Exposición de API keys: cuanto más tiempo vive una conexión en tu servidor, más superficie hay para que una clave larga se filtre.

Por eso la regla que escribieron en su template es directa: no proxear audio de larga duración (ni eventos de alta frecuencia) a través del servidor de la app. Los bytes en vivo van a un edge del proveedor o a un proceso Node dedicado, no a una función que espera terminar rápido.

¿WebSockets en Vercel: ya hay soporte nativo? Qué cambió y qué límites siguen

Sí, Vercel Functions ya sirven conexiones WebSocket en beta pública, según el changelog publicado en junio de 2026. La novedad está disponible en todos los planes y corre sobre Fluid Compute, pero eso no la vuelve apta para una sesión de transcripción de varios minutos sin cortes.

La conexión se fija a una sola instancia de función durante toda su vida, y con Fluid Compute esa misma instancia puede atender varios sockets a la vez. Eso ayuda con chat o colaboración, donde las conexiones son numerosas pero livianas. El tema es que la conexión se cierra cuando la función llega a su duración máxima configurada, así que el límite de siempre sigue ahí, solo que ahora con un nombre más prolijo. Sobre eso hablamos en si recién estás empezando con Vercel.

Otra cosa que cambia poco: el estado. La documentación de Vercel es clara en que una reconexión no garantiza volver a la misma instancia, y que tras un deploy nuevo las conexiones existentes se quedan en el deployment viejo hasta que cierran. Si guardás presencia, contadores o rooms en memoria, se pierden apenas el cliente reconecta a otra instancia. La solución que propone Vercel es un store externo tipo Redis, no variables locales.

¿Cuál es el patrón recomendado para streaming de audio en vivo en Next.js?

El patrón que usa TranscribeChirp reparte el trabajo en cuatro piezas con dueños claros: tu API arma la sesión, el proveedor recibe el audio directo, un endpoint de metering opcional cobra sobre la marcha y un endpoint de finalize cierra todo. Nada de esto toca el flujo de batch existente, que queda intacto.

El flujo concreto: el browser hace un POST a algo como /api/.../live/session y recibe un token de proveedor de vida corta más un jobId. Con eso abre el WebSocket directo contra Deepgram (o el ASR que uses) y empieza a recibir captions parciales. Cada pocos segundos, opcionalmente, pega a /api/.../live/meter para ir descontando créditos. Cuando termina, /api/.../live/finalize persiste la transcripción y cierra el job.

  • Tu API (auth): valida créditos, crea una fila de job y genera un token con alcance limitado de vida corta.
  • Proveedor (plano de datos): el browser conecta directo, sin pasar por tu backend, y los parciales vuelven en tiempo real.
  • Tu API (metering opcional): ticks idempotentes para avisar o cortar antes de que la billetera llegue a cero.
  • Tu API (finalize): guarda el transcript final, cobra el último minuto parcial y marca el job como terminado.

¿Qué debe devolver el endpoint que crea la sesión en vivo?

Tiene que devolver lo mínimo indispensable: un jobId, un token de vida corta con alcance limitado a esa sesión y su fecha de expiración. Nada más, y nunca la master API key del proveedor. Para más detalles técnicos, mirá al comparar Vercel con otras plataformas.

En el posteo de TranscribeChirp el shape queda así: type LiveSession = { jobId: string; token: string; expiresAt: string; }, agregando hints de endpoint o modelo si el proveedor los necesita. Si la pestaña del usuario se cierra de golpe, el finalize (o un sweeper que corra aparte) tiene que cerrar el job igual, así los créditos no quedan filtrándose en el aire.

¿Cómo se factura el consumo sin que el servidor controle el socket?

Se factura con un patrón floor/ceil que no necesita dueño del socket: precheck de al menos un minuto de créditos antes de arrancar, ticks cada cinco segundos aproximadamente cobrando por floor de minutos consumidos, y en el finalize se redondea hacia arriba (ceil) el último minuto parcial.

¿Y quién decide cuántos minutos facturables consumió un job? La base de datos, no el WebSocket. Como el metering llega por HTTPS desde el cliente (o desde un finalize de confianza), el socket puede quedarse tranquilo en el proveedor mientras tu backend lleva la cuenta real.

¿Cuándo conviene levantar un proceso Node dedicado en vez de conectar directo al proveedor?

Conviene un proceso propio cuando necesitás mezclar audio o hacer detección de voz antes de que el proveedor vea los bytes, cuando hay fan-in multi-party que ninguna sesión de un solo proveedor cubre, o cuando el protocolo que necesitás no lo puede hablar el browser de forma segura con un token corto. Relacionado: un caso de rollback automatizado en producción.

Hasta ese punto, generar un token y conectar directo es menos operación y menos formas de romperse. Fly, Railway o una VM entran en juego recién cuando el caso lo pide.

¿Cómo se aplica este patrón a otros streams en tiempo real, no solo audio?

Se aplica igual a cualquier feature de “texto aparece mientras el usuario sigue hablando”: chat en vivo, eventos de alta frecuencia, cualquier cosa que necesite bytes constantes durante minutos. Tratá a Vercel como plano de control (auth, jobs, créditos) y al proveedor como plano de datos (bytes y parciales).

Esa separación es la que mantuvo el flujo en vivo de TranscribeChirp shippable al lado del batch existente, sin pretender que una plataforma serverless es un relay de media siempre activo. Es la parte del diseño que vale la pena copiar, no la marca del proveedor de turno.

EnfoqueDónde corre el socketLímite principalCuándo usarlo
Proxy en API route de Next.jsDentro de la función de VercelCold starts, timeout, key expuestaNo recomendado para audio en vivo
WebSockets nativos de Vercel (beta)Instancia de función con Fluid ComputeAtado a duración máxima, sin fan-out sin store externoChat, colaboración, eventos cortos
Conexión directa browser-proveedorServidor del proveedor ASR (ej. Deepgram)Requiere token de vida corta y metering aparteTranscripción y traducción en vivo
Proceso Node dedicadoServidor propio (Fly, Railway, VM)Más ops, uptime a tu cargoMezcla de audio, VAD, multi-party
websockets en vercel diagrama explicativo

Errores comunes al armar streaming de audio en vivo sobre Vercel

  • Reusar la API route de batch para el audio en vivo: son cargas de trabajo distintas. El batch tolera cold starts, el audio en vivo no.
  • Mandar la master API key al cliente pensando que alcanza con un JWT genérico: si el token no tiene alcance limitado y TTL corto, un cliente comprometido puede reusarla fuera de su sesión.
  • Guardar estado de sesión en memoria del proceso al usar WebSockets nativos de Vercel: una reconexión puede caer en otra instancia y perder todo. Redis u otro store externo resuelve esto.
  • Cobrar solo al cerrar la sesión (ceil final) sin precheck de créditos: un usuario sin saldo puede abrir la sesión igual y generar consumo sin cobertura.

Preguntas Frecuentes

¿Qué es un proxy de WebSockets y por qué falla con audio en vivo en Vercel?

Un proxy de WebSockets es cuando tu servidor recibe la conexión del cliente y la reenvía a otro servicio, en vez de que el cliente conecte directo. En Vercel falla con audio en vivo porque la función que hace de proxy tiene cold starts y un tope de duración, y el audio necesita una conexión estable por minutos. Esto se conecta con lo que analizamos en los cambios recientes en el plan gratuito.

¿Cuánto dura una conexión WebSocket en una función de Vercel?

La conexión se cierra cuando la función alcanza su duración máxima configurada, según la documentación oficial de Vercel. El soporte de WebSockets requiere Fluid Compute habilitado, que es el default en proyectos nuevos creados desde abril de 2025.

¿Cuál es la alternativa a un proxy WebSocket para audio en tiempo real?

La alternativa es generar un token de vida corta desde tu API y que el browser conecte directo al proveedor de transcripción, como Deepgram. Tu backend queda como plano de control para auth y créditos, sin tocar los bytes de audio.

¿Cómo se factura un stream en vivo si no controlo el socket?

Se factura con un precheck de al menos un minuto de crédito, ticks periódicos que cobran por floor de minutos consumidos, y un ceil del minuto parcial final en el cierre de la sesión. La base de datos, no el socket, es la fuente de verdad sobre cuánto se consumió.

¿Vercel ya soporta WebSockets de forma nativa en 2026?

Sí, Vercel anunció soporte nativo de WebSockets en beta pública en su changelog de junio de 2026, disponible en todos los planes. Sigue sujeto a la duración máxima de la función y necesita un store externo para compartir estado entre instancias.

Conclusión

Lo que cambió con el soporte nativo de WebSockets en Vercel es que ahora podés servir conexiones bidireccionales sin armar un servidor Node aparte para casos livianos como chat. Lo que no cambió es el límite de duración de la función, y ahí es donde un proxy de audio en vivo sigue siendo mala idea.

Si estás por armar algo parecido, antes de escribir código anotá cuánto puede durar la sesión más larga que tu producto promete y comparala contra la duración máxima configurada en tu función de Vercel. Si la supera, no la proxees: generá un token corto y conectá al proveedor directo, como hizo TranscribeChirp con Deepgram. Es una regla simple, y evita descubrir el límite en producción con un usuario a mitad de una llamada.

Fuentes

Te puede interesar...