This episode covers how to see your app in production: monitoring frontend performance and errors, logging client issues and user metrics, real user monitoring and analytics, and production support and incident handling.

Apps run smoothly on a developer's machine, but production is another world: diverse devices, slow networks, and errors in unexpected places. Without observability, you only find out there's a problem after users complain.
This episode covers monitoring frontend performance and errors, logging client issues and user metrics, real user monitoring and analytics, and production support and incident handling.
When you're done, you can sleep well with a monitored app: errors surface quickly, performance is measured from real users, and incidents have a clear procedure.
Observability isn't just a tool, it's a culture: every production decision is backed by accountable data.
Errors that happen in a user's browser never appear in server logs. Tools like Sentry capture them along with context: stack trace, device, and the steps that triggered them:
npm install -D @sentry/sveltekit
npx sentry-wizard -i sveltekitnpx sentry-wizard -i sveltekit configures the Sentry plugin for SvelteKit automatically, including setup on both server and browser.
Errors in a load function should be caught so the page can still render partially. Catch and provide an informative fallback:
export async function load({ fetch }) {
try {
const res = await fetch("/api/laporan")
if (!res.ok) {
throw new Error("HTTP " + res.status)
}
return { data: await res.json() }
} catch (err) {
console.error("Gagal memuat laporan", err)
return { data: [], error: "Layanan sementara tidak tersedia" }
}
}try and catch turn an unexpected error into a renderable condition. console.error keeps a trace in the logs while users see a friendly message.
Not every error deserves reporting. Filter logging to meaningful events: uncaught errors, failed promises, and critical interactions. Excessive logging floods the team with noise and hides the signal.
Use structured context: event name, app version, and an anonymized user key. Logs without context can't be acted on.
Real user monitoring measures performance from real user devices, not a lab. The web-vitals library sends metrics like LCP and INP:
import { onCLS, onINP, onLCP } from "web-vitals"
function kirim(nama, nilai) {
fetch("/api/vitals", {
method: "POST",
body: JSON.stringify({ nama, nilai }),
})
}
onCLS((m) => kirim("CLS", m.value))
onINP((m) => kirim("INP", m.value))
onLCP((m) => kirim("LCP", m.value))onLCP calls a callback each time a metric is measured. Data is sent to your own endpoint or an analytics provider. Metrics from real users show whether optimizations actually worked.
Before adding analytics, think about what data is collected and how long it's kept. Analytics should be transparent and comply with privacy rules — aggregate metrics are usually enough for decision making.
Incidents can't be predicted, but they can be anticipated. Prepare a simple runbook: how to check status, read recent logs, and roll back a problematic release. A runbook shortens recovery time when everything goes wrong.
Keep the runbook somewhere reachable during an incident — not in a folder that's rarely opened. A document that can't be found when panicking is the same as not existing.
Record the timeline, root cause, and prevention steps. Every incident is input for improving monitoring: if an error happened undetected, fix the detection first before blaming the code.
Key takeaways:
Next, in episode 23, the final episode of this series, you'll learn stable modern features & future trends — Svelte's stable features, reactive framework and web performance trends, the Svelte ecosystem including SvelteKit and Svelte Native, and strategies for keeping your skills future-proof. Everything you've learned will be summarized in the series conclusion.