Skip to content

Search documentation

Find Svelte Patterns and Svelte reference pages.

No results for ""

Try a shorter query or a related Svelte term.

# Describe the Problem

If you need real-time updates — like live notifications, feed updates, or progress events — but don’t want the complexity of WebSockets or the overhead of polling, SSE offers a simpler, browser-native solution over standard HTTP connections.

playground
<script>
	import { onMount } from 'svelte'

	const messages = $state([])
	let connection = $state()

	const stop = () => {
		connection.close()
		connection = undefined
	}

	onMount(() => {
		connection = new EventSource('/sse')
		connection.onmessage = (e) => messages.push(JSON.parse(e.data))
		connection.onerror = stop

		return stop
	})
</script>

<p>Stops when a user clicks the button or after 10 events.</p>

<button onclick={stop} disabled={!connection}> Stop Connection </button>

<ol>
	{#each messages as message}
		<li>{new Date(message.time)}</li>
	{/each}
</ol>
export const GET = () => {
	const iterator = generateData()
	return new Response(createStream(iterator), {
		headers: {
			'Content-Type': 'text/event-stream',
			'Cache-Control': 'no-cache',
			Connection: 'keep-alive',
		},
	})
}

const createStream = (iterator) =>
	new ReadableStream({
		async pull(controller) {
			const { value, done } = await iterator.next()

			if (done) return controller.close()
			controller.enqueue(`data: ${JSON.stringify(value)}\n\n`)
		},
		cancel() {
			iterator.return?.()
		},
	})

async function* generateData() {
	// limit to 10 events
	for (let i = 0; i < 10; i++) {
		// limit events to 1 per second
		await new Promise((r) => setTimeout(r, 1000))

		yield { time: new Date() }
	}
}

# Reference