Introduction
Debugging a modern Laravel application used to mean sprinkling dd() calls through your codebase, staring at endless dumps, and hoping you found the right one. Laravel Telescope changed all of that by bringing an intelligent debugging and monitoring dashboard straight into your application. It's a free, open-source package built and maintained by the Laravel team itself — a first-party tool that lets you inspect requests, exceptions, database queries, log entries, jobs, mails, notifications, cache values, and more — all from a beautiful, intuitive interface that lives at /telescope inside your own application.
While Telescope's out-of-the-box experience is already impressive, unlocking its full potential requires thoughtful configuration: knowing which data to capture, how to throttle monitoring so it doesn't impact performance, how to protect it from exposure, and how to deploy it safely to production. This guide takes you from a fresh installation all the way to a hardened production deployment, complete with real-world scenarios, production-ready code, a custom watcher you can ship, and a security-first mindset.
Table of Contents
- Introduction
- Core Concepts
- Architecture Overview
- Step-by-Step Guide
- Real-World Examples
- Production Code Examples
- Comparison Table
- Best Practices
- Common Mistakes
- Performance Tips
- Security Considerations
- Deployment Notes
- Debugging Tips
- FAQ
- Conclusion
Core Concepts
Laravel Telescope sits above your application's request lifecycle, intercepting and recording events that happen around the HTTP layer and inside the framework. Rather than forcing you to instrument every function with manual logging, Telescope hooks into Laravel's internal event system and records high-value telemetry automatically. Understanding its three building blocks — the Recordable trait, watchers, and tags — will help you extend Telescope beyond its defaults.
The Recordable Trait
At the heart of Telescope is the Recordable trait. Any class that uses this trait gains access to Telescope's recording mechanism, which pushes events into the queue to be processed asynchronously. This separation from the request is what keeps your application responsive — Telescope never blocks the request that generated the data.
When a Recordable class wants to log something, it calls record(), which serializes the payload, wraps it in an IncomingEntry, tags it, and pushes a job to the queue. Because the job is dispatched rather than executed synchronously, the overhead is essentially a single queue push per event. The actual database write happens later, in a queue worker, so the end user never waits for Telescope.
Classes like Request, Exception, Query, Log, Job, Mail, Notification, and Cache all use this trait, so every HTTP request, thrown exception, database query, logged message, queued job, sent email, notification, and cache operation can be captured without any code changes on your part.
Watchers
Watchers are the pluggable components responsible for recording specific types of events. Each watcher is registered under a key in the Telescope configuration and has methods like recordRequest, recordException, recordQuery, recordJob, recordMail, and recordCache. When the relevant framework event fires, Telescope calls into the matching watcher method. This design makes it trivial to add new watchers or override existing ones with custom implementations.
A watcher receives the context object from Laravel — for example, a QueryExecuted event for the QueryWatcher, or a Request event for the RequestWatcher — and decides whether to record it. The watcher framework supports ignore_paths, ignore_methods, and ignore_validation_errors, giving you coarse-grained control without touching core code.
Tags
Tags let you annotate recorded events with your own metadata. A query watcher, for instance, can tag a query based on the model it touches, so you can later filter to all queries related to the user table. Tags are user-supplied key-value pairs, and the watcher framework makes it easy to attach context to your events.
Tags appear as a filterable chip list in the Telescope UI, and they're stored in the telescope_entry_tags table so filtering happens at the database level. A well-tagged entry is instantly searchable rather than buried in a log you have to read.
Architecture Overview
Understanding Telescope's architecture is essential before you enable it in production, because the cost of monitoring is real — and it scales with traffic. Here's how the pieces fit together, and where the bottlenecks are likely to appear.
The HTTP Layer
Telescope installs a dedicated route group (/telescope by default) served through Laravel's normal routing machinery. The TelescopeServiceProvider registers this route group when Telescope is booted, and the routes are protected by middleware that enforces the authorization gate you define. This is why access control is non-negotiable — the same middleware that protects Telescope is what keeps your internal telemetry from becoming a data leak.
The Database
All recorded events are persisted in your application's database, in tables created by Telescope's migrations: telescope_entries, telescope_entry_tags, telescope_monitoring, telescope_pending_entries, and telescope_failed_jobs.
The telescope_entries table is the workhorse. Each row represents one recorded event and has these columns: id, sequence_number, type, message, content, tags, created_at, and updated_at. The content column stores a JSON blob of the event payload, so a single query record might hold the query string, bindings, connection name, execution time, and stack trace all in one serializable structure.
Because every record eventually becomes a JSON row, database size grows linearly with traffic — which is the single biggest reason you must throttle recording in production.
The Queue
Recording is deferred to the queue. When an event is captured, an asynchronous job is pushed. A queue worker consumes these jobs and persists the entries. This means monitoring performance is largely decoupled from request latency.
The queue connection used for Telescope can be customized in the configuration. The recommended pattern is a dedicated queue — separate from your business jobs — so that a monitoring burst never starves your actual work. Because jobs are dispatched per event, you also get natural backpressure: if workers can't keep up, entries accumulate in the pending table, which Telescope surfaces in its own dashboard as a health indicator.
The entry repository abstraction lets you swap the default database backend for a custom implementation — for example, pushing entries to a cache layer or an external analytics sink for dashboards that need sub-second latency.
The Authorization Gate
Access to Telescope is controlled through Laravel's authorization gates. By default, Telescope allows access to the dashboard only if the canRegister callback returns true and, in production, the authenticated user passes the gate. This is where you map an admin role — often a boolean attribute like is_admin or a string email allowlist on your User model — and it's the last line of defense if recording is accidentally left on.
The request-to-record flow looks like this:
- An HTTP request arrives at your application.
- Laravel's kernel processes the request.
- At various points (before and after the request, during query execution, on exception, when a job is dispatched, when mail is sent), framework events fire.
- Telescope's listeners catch those events and call into the appropriate watcher.
- The watcher serializes the payload and pushes a record job to the queue.
- A queue worker processes the job and writes the entry to the database.
- An authorized user opens
/telescopeand browses the recorded events.
Step-by-Step Guide
Let's walk through installing and configuring Telescope from scratch, including the environment-specific steps that trip people up.
Installing the Package
Start by installing the package via Composer. This adds the package to your vendor directory and Composer lock file:
composer require laravel/telescopeRun the installer, which scaffolds the service provider, the configuration file, and the migrations:
php artisan telescope:installThis command publishes config/telescope.php, registers TelescopeServiceProvider in bootstrap/app.php, and makes the Telescope facade and middleware available. If you use config caching, refresh it:
php artisan config:cacheThen run your migrations to create the required tables:
php artisan migrateIf you're using MySQL or MariaDB, note that the telescope_entries.content column is a TEXT column by default. For very large payloads this can become a bottleneck, and you may want to bump it to MEDIUMTEXT or LONGTEXT after confirming the payloads fit your needs.
Configuring Access
Telescope's canRegister callback determines whether the package registers itself and therefore whether the /telescope route group even exists. By default it checks the APP_ENV, registering only in local environments:
'enable' => env('TELESCOPE_ENABLE', false),'canRegister' => fn () => env('TELESCOPE_ENABLE', false) || (app()->environment('local') && config('app.debug')),This default is exactly what you want on your local machine. In production, you want something more precise. Relying solely on env('TELESCOPE_ENABLE', true) is dangerous because an environment variable is shared across all users of the deployment, meaning anyone who can reach your application could reach the dashboard if they guessed the URL. The recommended production pattern is to gate access on an authenticated admin's session rather than a global env var — as shown in the production code section later — so the route group exists but refuses every anonymous request.
Configuring Watchers
In config/telescope.php, the watchers array lists which event collectors are active. You'll typically keep most enabled locally but selectively disable expensive ones in production. Each watcher supports an enabled flag, a store flag (whether to persist to the database or only display), and watcher-specific options.
The RequestWatcher records the full HTTP request — method, URI, headers, payload, session, and user. Because this includes form data, it can easily capture passwords and tokens, so ignore_paths and ignore_validation_errors are valuable.
The QueryWatcher records every database query, its bindings, its execution time, and the stack trace that called it. This is the watcher that catches N+1 problems, but it's also the most expensive to record at scale.
The ExceptionWatcher records every thrown exception with a full stack trace, the surrounding request, and the logged context. This is the watcher you want fully on in production — exceptions are rare and cheap to record.
The LogWatcher, JobWatcher, MailWatcher, NotificationWatcher, and CacheWatcher fill in the rest of the lifecycle. The JobWatcher records job dispatches and failures, which is how you catch a job that silently failed in the background.
A typical production watchers configuration disables the Request and Query watchers by default and re-enables them for targeted sessions:
<?phpreturn [ 'watchers' => [ 'Laravel\Telescope\Watchers\RequestWatcher' => [ 'enabled' => env('TELESCOPE_REQUEST_WATCHER', false), 'store' => env('TELESCOPE_STORE', false), 'ignore_methods' => ['Healthcheck', 'Ping', 'Metrics'], 'ignore_paths' => ['health', 'ping', 'metrics'], 'ignore_validation_errors' => true, ], 'Laravel\Telescope\Watchers\QueryWatcher' => [ 'enabled' => env('TELESCOPE_QUERY_WATCHER', false), 'store' => env('TELESCOPE_STORE', false), 'slow' => 100, 'ignore_paths' => ['health'], ], 'Laravel\Telescope\Watchers\ExceptionWatcher' => [ 'enabled' => env('TELESCOPE_EXCEPTION_WATCHER', true), 'store' => env('TELESCOPE_STORE', true), ], ],];Real-World Examples
Here are four scenarios where Telescope becomes indispensable in daily development and operations. Each one shows a different tab and a different kind of insight.
Finding the N+1 Problem
You ship a profile page that returns quickly locally, but users complain it's slow. In Telescope's Queries tab, you filter by the profile route and notice the orders query runs 47 times per page load instead of once. Each invocation is a separate query on the orders table, one per user. You add the eager relationship with('orders') and the count drops to a single query. The timeline view also shows where the queries occurred in the request, so you can see the exact line of code responsible.
Tracing a Flaky Exception
A customer reports an intermittent error but you can't reproduce it locally. The Exceptions tab shows the exception fired three times in the last hour, each with a full stack trace, a captured request payload, and the logged context. You see the exception originates from an external payment provider that occasionally returns a non-JSON body, and a null-coalescing guard resolves the issue. Because the payload is preserved, you can inspect the exact request body that triggered it — something you would never get from an error tracker alone.
Investigating a Queued Job Failure
Export emails aren't being sent, and your logs show nothing useful. The Jobs tab shows 342 pending jobs in the default queue. Clicking one reveals the serialized payload, the queue name, the number of attempts, and the failure reason. You find a malformed CSV column and fix the job to coerce the data, then clear the backlog. The failed jobs view surfaces jobs that crossed the maximum attempts, which is how you catch systemic problems in scheduled commands.
Auditing an Admin Action
You need to know who upgraded a user's subscription and when. Telescope doesn't record business events by default, but with custom entries you can capture exactly that. You tag each entry with an action, a user ID, and a session ID, then filter by tag in the dashboard. When you combine custom entries with the timeline view, you get an auditable sequence of related actions across requests.
Production Code Examples
Now let's write the code that makes Telescope safe and useful in production. This section covers conditional registration, custom entry recording, custom exception formatting, a reusable custom watcher, and a pruning command.
Conditional Registration for Production
Never rely solely on APP_ENV for enabling Telescope in production. Instead, gate access so that only signed-in administrators see the UI, and optionally record nothing unless explicitly enabled for an admin session. The cleanest place for this logic is an overridden register method in app/Providers/TelescopeServiceProvider.php:
public function register(): void{ Telescope::stopWatching(); if ($this->app->environment('local') || $this->adminMonitoringEnabled()) { $this->app->register(TelescopeServiceProvider::class); }}private function adminMonitoringEnabled(): bool{ return request()->user()?->hasRole('admin') && session()->get('telescope-monitoring') === true;}This pattern keeps the /telescope route group from even existing unless a condition is met, which is stronger than route-level authorization. The admin flips monitoring on with a session flag that expires after a short period, and flips it off afterward.
Restricting Access via the Gate
The gate is your fallback defense if Telescope does get registered in production. Define it in TelescopeServiceProvider's boot method:
Telescope::gate(fn ($user) => in_array($user->email, config('telescope.allowlist')) || $user->hasRole('admin'));With this in place, even if an environment variable accidentally enables Telescope, anonymous users and regular users are denied access. Always verify the gate with an unauthenticated request before you trust it.
Throttling the Request and Query Watchers
Don't record every request and every query in production. Configure the slow threshold on the QueryWatcher so you only capture queries that exceed a latency budget, and disable the RequestWatcher entirely except for targeted sessions:
'Laravel\Telescope\Watchers\QueryWatcher' => [ 'enabled' => env('TELESCOPE_QUERY_WATCHER', false), 'store' => env('TELESCOPE_STORE', true), 'slow' => 100, 'ignore_paths' => ['health', 'metrics', 'robots.txt'],],'Laravel\Telescope\Watchers\RequestWatcher' => [ 'enabled' => env('TELESCOPE_REQUEST_WATCHER', false), 'store' => env('TELESCOPE_STORE', false), 'ignore_paths' => ['health', 'metrics'],],The store flag is a subtle but powerful lever: it lets you view events live in the dashboard without persisting them to the database. During a debugging session, you can enable store-only collection, review it, then disable it — no database bloat, no retention work.
Formatting Exceptions to Remove Sensitive Data
Exceptions often contain stack traces that leak internal paths, configuration values, or user input. Customize formatting so only safe fields are stored:
Telescope::formatExceptionUsing(function (\Throwable $e, array $context = []) { return [ 'message' => $e->getMessage(), 'class' => $e::class, 'file' => basename($e->getFile()), 'line' => $e->getLine(), 'context' => [ 'user_id' => auth()->id(), 'trace_sample' => app()->environment('production'), ], ];});By storing only the basename of the file path, you avoid leaking your deployment directory structure to anyone with dashboard access.
Recording Custom Business Events
Log business-critical actions that Telescope doesn't capture out of the box, such as a subscription upgrade, a password change, or a permission grant. Custom entries are lightweight and go straight to the queue:
use Laravel\Telescope\Telescope;use Laravel\Telescope\IncomingEntry;public function upgradeToPro(): void{ $user = auth()->user(); $oldPlan = $user->subscription->plan; $user->subscription->upgradeTo('pro'); Telescope::entry( IncomingEntry::make('subscription_upgrade') ->tags(['user_id' => $user->id, 'plan' => 'pro']) ->content([ 'user_id' => $user->id, 'old_plan' => $oldPlan, 'new_plan' => 'pro', ]) );}Each call to Telescope::entry dispatches a queued job. Because the payload is small and JSON-serializable, this adds virtually no request latency, and the tags make the events immediately filterable in the dashboard.
Creating a Custom Watcher
Sometimes the built-in watchers aren't enough. Suppose you want to record when a third-party payment provider is called. You can create a custom watcher that listens to a framework event and records it as a custom entry:
php artisan make:watcher PaymentWatcher<?phpnamespace App\Telescope\Watchers;use Laravel\Telescope\IncomingEntry;use Laravel\Telescope\Watchers\Watcher;class PaymentWatcher extends Watcher{ public function record(array $context): void { Telescope::entry( IncomingEntry::make('payment_provider_call') ->tags(['provider' => $context['provider']]) ->content([ 'provider' => $context['provider'], 'endpoint' => $context['endpoint'], 'status' => $context['status'], 'duration_ms' => $context['duration_ms'], ]) ); }}Register it in config/telescope.php under the watchers key, and your application starts recording payment provider interactions alongside Laravel's own telemetry.
Pruning Old Entries Safely
Telescope never deletes entries on its own. Add a scheduled task that prunes entries older than your retention window. Here's a safe, batched artisan command:
<?phpdeclare(strict_types=1);namespace App\Console\Commands;use Illuminate\Console\Command;use Illuminate\Support\Facades\DB;class PruneTelescopeEntries extends Command{ protected $signature = 'telescope:prune {--days=30}'; protected $description = 'Prune Telescope entries older than N days'; public function handle(): int { $cutoff = now()->subDays((int) $this->option('days')); $total = 0; while (true) { $deleted = DB::table('telescope_entries') ->where('created_at', '<', $cutoff) ->chunkById(1000, function ($entries) use (&$total) { $total += $entries->delete(); }); if ($deleted === 0) { break; } } $this->info("Pruned {$total} entries older than 30 days."); return Command::SUCCESS; }}Register it in app/Console/Kernel.php's schedule method, and chunked deletes in batches of 1,000 will prevent locking the table for a long time while memory stays flat.
Comparison Table
Here's how Telescope compares to the main alternatives for Laravel debugging and monitoring. Each row is a decision dimension that matters when you choose your tooling.
| Feature | Laravel Telescope | Manual Logging | Laravel Horizon | Third-Party APM/SaaS |
|---|---|---|---|---|
| Setup complexity | Low — Composer package + migrations | High — code every time | Medium — config + worker | Low — API key + snippet |
| Request inspection | Visual dashboard | Manual dumps/logs | Not applicable | Yes |
| Query inspection | Yes, with timing and traces | Manual SQL logging | No | Varies |
| Job and queue visibility | Yes — pending, failed, retry | Database inspection | Yes — specialized queue UI | Yes |
| Exception detail | Full trace + context + payload | Depends on config | Via failed jobs | Often richer |
| Cost | Free, self-hosted | Free | Free | Recurring subscription |
| Where data lives | Your database | Your database/logs | Your database | Vendor cloud |
| Real-time alerting | No — dashboard only | No | Limited | Yes — typical feature |
| Best for | Local debugging and on-call triage | Compliance and audit logs | Queue performance monitoring | 24/7 production monitoring |
The practical takeaway: Telescope is your local-first, self-hosted debugging Swiss Army knife. It is not a drop-in replacement for a dedicated production monitoring service when you need 24/7 alerting, off-site data storage, and SLA reporting. The best setups use Telescope for development and incident triage, while a dedicated APM or log aggregation platform handles production observability.
Best Practices
- Never deploy with recording enabled on all traffic. Use an environment variable flag or an admin session flag, and never enable Telescope globally in production.
- Throttle high-volume watchers. Disable or slow down the Request and Query watchers in production. Keep the ExceptionWatcher on — exceptions are rare and cheap to record — and rely on your APM for continuous query monitoring.
- Exclude sensitive routes and paths. Use
ignore_pathsto omit health checks, ping endpoints, metrics, and any route that could leak internal state. - Store only what you need. Prefer
store=falseduring active debugging sessions so events are visible live but never persisted. - Restrict access via the gate. Never leave Telescope open to the world. The UI exposes internal queries, stack traces, queued payloads, and logged credentials — it is one of the most sensitive routes in your application.
- Tag business events. Use tags on custom entries so you can filter and search meaningfully.
- Monitor Telescope's own health. Watch the pending entries count, database size, and worker lag. If Telescope falls behind, recording is too aggressive.
Common Mistakes
- Enabling Telescope via
APP_ENV=productionalone. This broadcasts Telescope to anyone who can reach your application if you forgot to harden the gate. An environment variable is shared across all users of the deployment. - Recording every request in production. At even modest traffic, this fills the database and degrades performance for everyone. Request and query payloads scale with visits, not with bugs.
- Capturing request bodies blindly. JSON payloads may contain passwords, API keys, and PII. Configure
storeand body filtering carefully, and scrub sensitive fields from custom entries and exceptions. - Forgetting that queue workers are required. Without a running worker, entries pile up in the pending table and never render. A stale dashboard is misleading.
- Ignoring the cleanup strategy. Old entries are never auto-archived, so retention must be managed manually. Without pruning, the table becomes a maintenance burden and slows dashboard queries.
- Assuming Telescope replaces logging or APM. Telescope is an interactive debugger and developer tool. It complements logging, log aggregation, and APM tools rather than replacing them.
Performance Tips
- Use a dedicated queue. Run Telescope jobs on a separate queue so monitoring load doesn't compete with business-critical jobs. Map Telescope entries to a monitor queue in your provider.
- Use a dedicated database connection. Point Telescope at its own read replica or separate database to isolate I/O. This keeps monitoring queries from affecting your primary workload.
- Limit stored entries. Set a maximum entry age and prune on a schedule. A 30-day window with automatic pruning keeps the table small and queries fast.
- Avoid recording large payloads. Configure request body storage limits and exclude binary-heavy responses. For custom entries, keep the content array small — store an ID, not an entire model tree.
- Use store-only collection for sessions. During an investigation, enable
store=falseso events are visible in the UI without writing to disk. This eliminates write load entirely for the session. - Watch the sequence number. Entries are ordered by a sequence number, so heavy insert volume can cause contention. Throttling volume is more effective than optimizing the insert itself.
Security Considerations
Telescope is arguably the single most sensitive route in a Laravel application, because the dashboard surface exposes internal queries, stack traces, queued payloads, and potentially logged credentials. Treat it accordingly, layer by layer.
- Authentication and authorization. Require a signed-in admin and restrict the gate to known emails or admin roles. Never serve Telescope to anonymous users.
- Request body scrubbing. Configure Telescope to exclude sensitive fields from stored request bodies. Fields like
password,api_key,api_secret,credit_card, andtokenshould never be persisted. - Route protection and hosting. Telescope lives under
/telescopeby default, a predictable path. Host it behind middleware that enforces IP allowlisting if you can, and never expose it through public CDNs or reverse proxies that strip authentication. - Data retention. Entries contain production data, which may include PII. Implement a retention policy and delete entries older than your compliance window. Document the retention period and pruning mechanism.
- Environment discipline. Never commit
TELESCOPE_ENABLE=trueto version control. Use one-time flip-flops tied to session state for incident investigations. - Audit the gate before you trust it. Test Telescope with an unauthenticated request and with a non-admin authenticated request. If either succeeds, you have a security hole.
Deployment Notes
When deploying Telescope, think about these moving parts, in order.
- Enabling it. Use a session-based or environment-flag mechanism that only allows a signed-in admin to see the UI. The flag should expire after a short period, ideally 30 minutes, so recording can't stay on accidentally.
- Running workers. Ensure your queue workers are healthy and consuming the Telescope queue. Monitor the pending entries count as a proxy for worker health.
- Database sizing. Telescope tables grow with traffic. Plan storage, add indexes if you query large entry sets, and consider partitioning or archiving old entries if you expect very high volume.
- Rollback safety. If you need to disable recording mid-incident, flipping the flag off stops new entries; it does not retroactively delete existing ones. Session-based flags are preferable because you can flip them off in seconds.
- Observability of Telescope itself. Monitor Telescope's database size and worker lag as part of your standard dashboard. If Telescope becomes slow to load, that's a signal that recording is too aggressive.
- Local versus production parity. Local Telescope should be fully enabled so you get the same visibility you had during development. Document how admins enable it on the production deployment.
Debugging Tips
- Use the filter bar. Type route names, query snippets, or exception classes to slice through thousands of entries instantly.
- Sort by duration. The Queries tab sorts by execution time by default; flip the column to find slow queries at a glance.
- Inspect the timeline. The Requests tab shows a timeline of sub-requests, helper calls, and view renders, making it easy to spot where time is spent.
- Use tags to scope context. Tag entries during an incident with an incident ID so you can reconstruct the exact sequence.
- Check pending entries. If the dashboard looks stale, check the pending entries table to see if workers are falling behind.
- Compare request payloads. The Requests tab lets you view the raw request and response, including headers and cookies.
- Disable selectively. Rather than shutting Telescope off, disable individual watchers through the configuration to isolate noisy collectors.
FAQ
Is Laravel Telescope free?
Yes. Telescope is free and open-source, maintained by the Laravel team, and included with the Laravel ecosystem. There is no licensing cost, and self-hosting keeps your telemetry data under your control.
Does Telescope slow down my application?
Recording is deferred to the queue, so it has minimal impact on request latency. However, storing and querying large volumes of entries can strain your database, which is why throttling, dedicated queues, and retention are critical in production.
Can I use Telescope in production?
Yes, but only with strict access controls, throttled watchers, scrubbed payloads, and a retention policy. Never leave it enabled for all traffic and all users. The recommended pattern is session-gated monitoring for admins.
How do I add custom entries?
Use Telescope::entry() with an IncomingEntry builder, as shown in the production code examples. You can attach tags and arbitrary JSON content, and each entry is queued for asynchronous persistence.
How do I delete old Telescope entries?
Telescope doesn't auto-delete entries. Create a scheduled task or artisan command that prunes entries older than your retention period, using chunked deletes to avoid locking the table.
Does Telescope replace logging or monitoring?
No. Telescope is an interactive debugger and developer tool. It complements logging, log aggregation, and APM tools rather than replacing them — think of it as a local-first investigation surface.
How do I restrict Telescope to admin users only?
Define a canRegister callback and use Telescope::gate() to authorize only authenticated administrators based on email, role, or any custom check. Combine this with a session flag in production so the dashboard never serves anonymous users.
What tables does Telescope create?
Telescope creates telescope_entries, telescope_entry_tags, telescope_monitoring, telescope_pending_entries, and telescope_failed_jobs. The telescope_entries table holds one row per recorded event.
Conclusion
Laravel Telescope turns debugging from a guessing game into a visual, searchable investigation. From N+1 queries to flaky exceptions and stalled jobs, it gives you the context you need without touching your application code — and with custom entries and watchers, you can extend it to capture exactly the events that matter to your business. The key to keeping Telescope valuable long-term is discipline: throttle what you record, protect what you expose, tag what you want to find, and prune what you keep.
Treat Telescope as your local-first, self-hosted investigation surface, and pair it with a dedicated APM or log aggregation platform for 24/7 production monitoring. Used this way, it becomes the fastest path from a reported bug to a root cause — which is exactly what every developer wants.
Ready to put it to work? Run composer require laravel/telescope && php artisan telescope:install in your next project and explore the Queries and Exceptions tabs on your very first request. Then share your own Telescope tips — what's the most surprising thing Telescope caught for you?