Getting Started
Mount the Telescope dashboard in an existing NestJS app — install core + ui, import two modules, and open /telescope. Zero-config SQLite by default; swap the storage adapter when you're ready.
The fastest way to get Telescope running is two imports: the core module and the UI module. Request and exception capture wire themselves automatically, and a zero-config SQLite store is on by default — so you import, boot, and open /telescope. Most apps are done in under five minutes.
Prerequisites
- Node.js 20+
- NestJS 11+ for the UI module (core works on 10+)
- Works on Express and Fastify
Step 1 — Install
Install core and the dashboard:
pnpm add @dudousxd/nestjs-telescope @dudousxd/nestjs-telescope-uinpm install @dudousxd/nestjs-telescope @dudousxd/nestjs-telescope-uiStep 2 — Import the modules
Add both modules to your root module. TelescopeModule.forRoot() wires request and exception capture and turns on the default SQLite store and pruner; TelescopeUiModule.forRoot() serves the dashboard SPA.
import { Module } from '@nestjs/common';
import { TelescopeModule } from '@dudousxd/nestjs-telescope';
import { TelescopeUiModule } from '@dudousxd/nestjs-telescope-ui';
@Module({
imports: [
TelescopeModule.forRoot({
// dev: rich capture, open gate. prod: flip enabled + supply an authorizer.
enabled: process.env.NODE_ENV !== 'production',
authorizer: () => true, // gates the API; defaults to deny in production
prune: { after: '24h' },
}),
TelescopeUiModule.forRoot(),
],
})
export class AppModule {}Done. Boot the app and open http://localhost:3000/telescope. The dashboard polls /telescope/api/* and shows captured entries — type tabs plus live polling — and, on an entry, the correlated batch: the request and everything it caused.
Production gate
The API gate denies in production by default. In prod you must set enabled: true and supply an authorizer (or wire dashboard auth) — otherwise the dashboard returns 403. This is a default, not an afterthought: capture runs with redaction always on, and the gate is closed until you open it.
Step 3 — Hit the headless API
The dashboard is optional — everything it shows comes from a plain JSON API you can curl, script, or build your own admin against:
| Method & path | Returns |
|---|---|
GET /telescope/api/entries | A page of captured entries (filter by type, tag, batch, family, time). |
GET /telescope/api/entries/:id | One entry plus its correlated batch — the request and everything it caused. |
GET /telescope/api/pulse?window=1h | Per-type counts, slowest entries, top exceptions, N+1 occurrences. |
GET /telescope/api/queues?window=1h | Per-queue throughput, runtime/wait-time percentiles, failure rate. |
GET /telescope/api/timeseries?window=1h&buckets=60 | Bucketed throughput — the data behind the sparkline. |
GET /telescope/api/health | Telescope's own self-overhead: capture cost, buffer pressure, flush stats, drops. |
The zero-config SQLite default
Out of the box Telescope persists entries to a per-process SQLite store. No connection string, no migration, no table setup — it just works on the first boot. That's the right default for local development and single-process apps.
It is per-process, though: each replica has its own SQLite, so in a multi-instance deployment the dashboard would only show entries from the pod that served the request. When you scale out, pick a shared storage adapter.
Step 4 — Pick your storage adapter
Swap the default by passing a storage provider to forRoot. Every adapter implements the same StorageProvider SPI, so the API, dashboard, and pruner treat them identically.
| Adapter | Use it when | Package |
|---|---|---|
| SQLite (default) | Local dev, single process. | built into core |
| MikroORM (MySQL / SQLite) | You already run MikroORM and want Telescope in your own DB — no Redis. | -mikro-orm |
| Redis | Multi-instance: every replica reads/writes one shared store, so the dashboard aggregates the whole cluster. | -redis |
| In-memory | Tests. | -testing |
For example, to share one store across replicas via Redis:
import Redis from 'ioredis';
import { RedisStorageProvider } from '@dudousxd/nestjs-telescope-redis';
TelescopeModule.forRoot({
storage: new RedisStorageProvider(new Redis(process.env.REDIS_URL)),
});See Storage for the SPI and the storage packages for each adapter's wiring.
Step 5 — Add watchers
Core captures requests and exceptions on its own. Everything else — queries, jobs, mail, cache, schedules, events, logs, Redis commands — is a watcher you add to the watchers array. Each watcher is its own package; install the ones that match your stack.
To capture outbound HTTP (no peer dependency — it instruments the global fetch and sanitizes secret query params), add the built-in watcher:
import { TelescopeModule, HttpClientWatcher } from '@dudousxd/nestjs-telescope';
TelescopeModule.forRoot({ watchers: [new HttpClientWatcher({ slowMs: 1000 })] });Calls through @nestjs/axios bypass fetch — pass an axios source to capture them too (see the HttpClientWatcher reference).
To capture queries from MikroORM, wire its logger so each query correlates to the request that triggered it:
import { TelescopeModule, TelescopeService } from '@dudousxd/nestjs-telescope';
import { telescopeMikroOrmLogger } from '@dudousxd/nestjs-telescope-mikro-orm';
MikroOrmModule.forRootAsync({
inject: [TelescopeService],
useFactory: (telescope: TelescopeService) => ({
// ...your config
debug: ['query'],
loggerFactory: telescopeMikroOrmLogger((input) => telescope.record(input)),
}),
});Browse the Packages section for every watcher, storage, and queue manager — each page is a complete, copy-pasteable setup.
Next steps
- Capture & correlation — how watchers, batches, and ALS turn scattered events into one navigable flow
- Storage — the
StorageProviderSPI, self-healing schema, and the adapter table - Performance — why capture doesn't slow your app, and the
/healthcard that proves it - Dashboard tour — the full UI: overview, entries, traces, queues console, schedules, and alerts
- Dashboard auth — gate the dashboard to your logged-in admins, all the way to prod
- AI exception diagnosis — a Diagnose-with-AI button and alert enrichment
- MCP server — connect Claude Code / Cursor and debug straight from captured data
- Configuration reference — every
forRoot()option in one table - Reporting frontend errors — browsers POST errors straight to Telescope
- Archiving to S3 — export entries before the pruner deletes them
Telescope
Laravel Telescope, redesigned for NestJS — a headless observability console that correlates every request, query, job, mail, cache hit, and exception under one batch, with a pluggable store and an optional dashboard.
Capture & correlation
How watchers, batches, and AsyncLocalStorage turn scattered events into one navigable flow — the request and everything it caused, in capture order.