Filament Multi-Panel Auth &amp; Table Query Tuning | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Filament at Scale: Custom Panels, Multi-Panel Auth, and Table Query Tuning        On this page       1. [  Why Multi-Panel Filament Gets Messy Fast ](#why-multi-panel-filament-gets-messy-fast)
2. [  Registering Separate Auth Guards Per Panel ](#registering-separate-auth-guards-per-panel)
3. [  Scoping Resources to the Authenticated Panel User ](#scoping-resources-to-the-authenticated-panel-user)
4. [  Table Query Tuning at Scale ](#table-query-tuning-at-scale)
5. [  Disable Exact Pagination Counts ](#disable-exact-pagination-counts)
6. [  Eager-Load Strategically ](#eager-load-strategically)
7. [  Index the Columns You Search and Sort ](#index-the-columns-you-search-and-sort)
8. [  Defer Expensive Aggregates ](#defer-expensive-aggregates)
9. [  Key Takeaways ](#key-takeaways)

  ![Filament at Scale: Custom Panels, Multi-Panel Auth, and Table Query Tuning](https://cdn.msaied.com/250/a3ee552917cb11dfaf2dedf5a5ee29b3.png)

  #filament   #laravel   #multi-tenant   #performance   #postgresql  

 Filament at Scale: Custom Panels, Multi-Panel Auth, and Table Query Tuning 
============================================================================

     20 Jun 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

  9 sections  

1. [  01   Why Multi-Panel Filament Gets Messy Fast  ](#why-multi-panel-filament-gets-messy-fast)
2. [  02   Registering Separate Auth Guards Per Panel  ](#registering-separate-auth-guards-per-panel)
3. [  03   Scoping Resources to the Authenticated Panel User  ](#scoping-resources-to-the-authenticated-panel-user)
4. [  04   Table Query Tuning at Scale  ](#table-query-tuning-at-scale)
5. [  05   Disable Exact Pagination Counts  ](#disable-exact-pagination-counts)
6. [  06   Eager-Load Strategically  ](#eager-load-strategically)
7. [  07   Index the Columns You Search and Sort  ](#index-the-columns-you-search-and-sort)
8. [  08   Defer Expensive Aggregates  ](#defer-expensive-aggregates)
9. [  09   Key Takeaways  ](#key-takeaways)

       Why Multi-Panel Filament Gets Messy Fast
----------------------------------------

Filament v3 and v4 make it trivial to spin up a second panel — `php artisan make:filament-panel`. The trouble starts when that second panel needs its own auth guard, its own user model, and table queries that do not bleed across tenant or role boundaries. Most tutorials stop at "add a panel, ship it." Production does not.

---

Registering Separate Auth Guards Per Panel
------------------------------------------

Each `PanelProvider` exposes an `authGuard()` method. Pair it with a dedicated guard in `config/auth.php`:

```php
// config/auth.php
'guards' => [
    'admin' => [
        'driver'   => 'session',
        'provider' => 'admins',
    ],
    'partner' => [
        'driver'   => 'session',
        'provider' => 'partners',
    ],
],
'providers' => [
    'admins'   => ['driver' => 'eloquent', 'model' => App\Models\Admin::class],
    'partners' => ['driver' => 'eloquent', 'model' => App\Models\Partner::class],
],

```

```php
// app/Providers/Filament/AdminPanelProvider.php
public function panel(Panel $panel): Panel
{
    return $panel
        ->id('admin')
        ->path('admin')
        ->authGuard('admin')
        ->login()
        ->colors(['primary' => Color::Slate]);
}

```

```php
// app/Providers/Filament/PartnerPanelProvider.php
public function panel(Panel $panel): Panel
{
    return $panel
        ->id('partner')
        ->path('partner')
        ->authGuard('partner')
        ->login()
        ->colors(['primary' => Color::Teal]);
}

```

Filament stores the authenticated user in the guard you specify. `auth('partner')->user()` inside a Partner resource will never return an `Admin` — as long as you never fall back to the default guard.

---

Scoping Resources to the Authenticated Panel User
-------------------------------------------------

The most common production bug: a resource's `getEloquentQuery()` is not scoped, so one panel's users can read another's data.

```php
// app/Filament/Partner/Resources/OrderResource.php
public static function getEloquentQuery(): Builder
{
    $partner = auth('partner')->user();

    return parent::getEloquentQuery()
        ->whereBelongsTo($partner)
        ->withoutGlobalScope(SoftDeletingScope::class);
}

```

Always override `getEloquentQuery()` in every resource that lives inside a scoped panel. Do not rely on global Eloquent scopes alone — they are easy to accidentally remove in tests or eager loads.

---

Table Query Tuning at Scale
---------------------------

Filament tables issue a `COUNT(*)` for pagination and a `SELECT` for the visible page. On a table with 500 k rows and several `->searchable()` columns, that count query alone can take seconds.

### Disable Exact Pagination Counts

```php
->paginated([10, 25, 50])
->paginationPageOptions([10, 25, 50])
->defaultPaginationPageOption(25)
->countQuery(fn (Builder $query) => $query->toBase()) // skip count

```

Filament v4 exposes `simplePaginate()` via `->simplePagination()` on the table. Use it when you do not need "page X of Y":

```php
Table::make()
    ->simplePagination()

```

### Eager-Load Strategically

Filament will not automatically eager-load relationships referenced in columns. Declare them explicitly:

```php
Table::make()
    ->query(
        Order::query()
            ->with(['partner:id,name', 'items:id,order_id,sku'])
    )

```

Avoid `->with('*')` — it defeats the purpose of column-level selection.

### Index the Columns You Search and Sort

Every `->searchable()` column that hits the database needs an index. For multi-column search Filament generates an `OR LIKE` clause:

```sql
WHERE (orders.reference LIKE ? OR partners.name LIKE ?)

```

A composite index will not help here. Use full-text indexes (MySQL `FULLTEXT`, PostgreSQL `GIN` with `pg_trgm`) or push search to a dedicated search engine for large datasets.

```sql
-- PostgreSQL
CREATE INDEX orders_reference_trgm_idx
    ON orders USING GIN (reference gin_trgm_ops);

```

### Defer Expensive Aggregates

If a column shows a sum or count, do not compute it in the main query. Use a sub-select or a pre-computed column:

```php
TextColumn::make('items_total')
    ->label('Total Items')
    ->getStateUsing(fn (Order $record) => $record->items_count)
    ->sortable(query: fn (Builder $q, string $dir) =>
        $q->orderBy('items_count', $dir)
    ),

```

Load `items_count` via `->withCount('items')` in `getEloquentQuery()` once, rather than triggering a sub-query per row.

---

Key Takeaways
-------------

- Register a dedicated `authGuard` in every `PanelProvider`; never share guards between panels.
- Always override `getEloquentQuery()` in scoped resources — do not trust global scopes alone.
- Switch to `->simplePagination()` on large datasets to eliminate the `COUNT(*)` round-trip.
- Declare eager loads in the table query, not in column definitions.
- Add `pg_trgm` or `FULLTEXT` indexes on searchable columns before traffic hits them.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Ffilament-at-scale-custom-panels-multi-panel-auth-and-table-query-tuning&text=Filament+at+Scale%3A+Custom+Panels%2C+Multi-Panel+Auth%2C+and+Table+Query+Tuning) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Ffilament-at-scale-custom-panels-multi-panel-auth-and-table-query-tuning) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Can two Filament panels share the same User model but use different guards?        Yes. Point both guards at the same Eloquent provider but use different session keys by giving each guard a unique name. Filament isolates sessions per guard, so a user logged into one panel will not be automatically authenticated in the other. 

      Q02  Does simplePagination break Filament's built-in page-size selector?        The page-size dropdown still renders, but navigation is limited to previous/next links because the total row count is not fetched. For most admin tables with large datasets this trade-off is worth the query savings. 

      Q03  How do I prevent a resource from appearing in the wrong panel?        Register resources explicitly in each PanelProvider via -&gt;resources([...]) rather than relying on auto-discovery. Auto-discovery scans all registered resource classes regardless of panel, which can expose resources unintentionally. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Laravel AI SDK: Tool-Calling Agents and Conversation Persistence](https://cdn.msaied.com/260/8c84f424e42da01993c9ba4b8eb19655.png) laravel ai agents 

### Laravel AI SDK: Tool-Calling Agents and Conversation Persistence

Build reliable tool-calling AI agents in Laravel using the Prism package. Learn how to wire tools, persist con...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 21 Jun 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-ai-sdk-tool-calling-agents-and-conversation-persistence) [ ![Laravel Livewire v3 Internals: Morph Markers, JS Hooks, and Alpine Integration](https://cdn.msaied.com/259/e8ce445f021c2b26ebe4dd5da50014f8.png) livewire laravel alpine 

### Laravel Livewire v3 Internals: Morph Markers, JS Hooks, and Alpine Integration

Go beyond the docs: understand how Livewire v3 diffs the DOM with morph markers, intercept the lifecycle with...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 21 Jun 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-livewire-v3-internals-morph-markers-js-hooks-and-alpine-integration) [ ![Laravel Package Development: Service Providers, Auto-Discovery, and Config Merging](https://cdn.msaied.com/258/673a80fa8e42ae375a4bba21bdcd92ea.png) laravel packages service-providers 

### Laravel Package Development: Service Providers, Auto-Discovery, and Config Merging

Build a production-ready Laravel package from scratch — covering service provider design, auto-discovery via c...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 21 Jun 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-package-development-service-providers-auto-discovery-and-config-merging-1) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
