Renderz Studio
Academia
Proyectos
Servicios
Arsenal
Repo
Herramientas
Skills
El Oráculo
Guía Gratis
← El Arsenal
ArquitecturaAvanzado35 min

Streaming y SSE en Tiempo Real

Server-Sent Events · chunks · UX fluida · respuestas que aparecen letra a letra

StreamingSSERealtime
✓ Guía gratuita · Acceso completo

Mapa rápido · salta al paso que te interese

Fundamentos SSE

Qué es y cómo funciona Server-Sent Events

Backend streaming

API route que emite chunks

Frontend consumer

React hook para consumir el stream

01

Fundamentos: SSE vs WebSockets vs Polling

Server-Sent Events es un estándar HTTP que permite al servidor enviar datos al cliente de forma continua sobre una única conexión. Es más simple que WebSockets y perfecto para streaming de IA.

MétodoDirecciónComplejidadCaso de uso
SSEServer → ClientBajaStreaming de texto, notificaciones
WebSocketsBidireccionalMediaChat en tiempo real, juegos
Long PollingClient → ServerAltaFallback legacy

Tip Pro

SSE funciona sobre HTTP/1.1 y HTTP/2, pasa por proxies sin problemas, y se reconecta automáticamente si la conexión se pierde.
02

Backend: API route con streaming

El truco está en devolver un ReadableStream y configurar los headers correctos. El content-type debe ser text/event-stream.

app/api/chat/route.ts
import Anthropic from '@anthropic-ai/sdk'

const anthropic = new Anthropic()

export async function POST(req: Request) {
  const { messages } = await req.json()

  const stream = await anthropic.messages.stream({
    model: 'claude-sonnet-4-20250514',
    max_tokens: 1024,
    messages,
  })

  // Crear un ReadableStream desde el stream de Anthropic
  const readableStream = new ReadableStream({
    async start(controller) {
      for await (const event of stream) {
        if (event.type === 'content_block_delta' &&
            event.delta.type === 'text_delta') {
          // Formato SSE: "data: contenido\n\n"
          controller.enqueue(
            new TextEncoder().encode(`data: ${JSON.stringify({ text: event.delta.text })}\n\n`)
          )
        }
      }
      controller.enqueue(new TextEncoder().encode('data: [DONE]\n\n'))
      controller.close()
    }
  })

  return new Response(readableStream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
    },
  })
}
03

Frontend: consumir el stream en React

En el cliente, usamos fetch con un reader para procesar los chunks según llegan.

hooks/useStreamingChat.ts
import { useState, useCallback } from 'react'

export function useStreamingChat() {
  const [response, setResponse] = useState('')
  const [isLoading, setIsLoading] = useState(false)

  const sendMessage = useCallback(async (messages: Array<{role: string, content: string}>) => {
    setIsLoading(true)
    setResponse('')

    const res = await fetch('/api/chat', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ messages }),
    })

    const reader = res.body?.getReader()
    const decoder = new TextDecoder()

    while (reader) {
      const { done, value } = await reader.read()
      if (done) break

      const chunk = decoder.decode(value)
      const lines = chunk.split('\n')

      for (const line of lines) {
        if (line.startsWith('data: ') && line !== 'data: [DONE]') {
          const data = JSON.parse(line.slice(6))
          setResponse(prev => prev + data.text)
        }
      }
    }

    setIsLoading(false)
  }, [])

  return { response, isLoading, sendMessage }
}

Tip Pro

Para producción, considera usar el Vercel AI SDK que maneja todo esto con useChat y useCompletion.

Guías relacionadas

Vercel AI SDK Completo

Streaming nativo con useChat

Function Calling Avanzado

Tools con streaming

¿Quieres el sistema completo?

500+ páginas, 25 capítulos, código de producción, acceso a todas las guías del Arsenal.

Curso Completo · €29

PayPal · Acceso inmediato

¿Hablamos?