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

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

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

  [ home ](https://www.msaied.com)    [ articles ](https://www.msaied.com/articles)    Filament at Scale: Multi-Panel Auth, Custom Panels, and Table Query Tuning        On this page       1. [  The Problem With One Panel for Everything ](#the-problem-with-one-panel-for-everything)
2. [  Registering a Second Panel ](#registering-a-second-panel)
3. [  Separate Guards and User Models ](#separate-guards-and-user-models)
4. [  Sharing Resources Across Panels ](#sharing-resources-across-panels)
5. [  Table Query Tuning at Scale ](#table-query-tuning-at-scale)
6. [  Override the Table Query ](#override-the-table-query)
7. [  Disable Count-Based Pagination ](#disable-count-based-pagination)
8. [  Index Your Sort Columns ](#index-your-sort-columns)
9. [  Takeaways ](#takeaways)

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

  #filament   #laravel   #multi-tenant   #performance  

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

     16 Aug 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

  9 sections  

1. [  01   The Problem With One Panel for Everything  ](#the-problem-with-one-panel-for-everything)
2. [  02   Registering a Second Panel  ](#registering-a-second-panel)
3. [  03   Separate Guards and User Models  ](#separate-guards-and-user-models)
4. [  04   Sharing Resources Across Panels  ](#sharing-resources-across-panels)
5. [  05   Table Query Tuning at Scale  ](#table-query-tuning-at-scale)
6. [  06   Override the Table Query  ](#override-the-table-query)
7. [  07   Disable Count-Based Pagination  ](#disable-count-based-pagination)
8. [  08   Index Your Sort Columns  ](#index-your-sort-columns)
9. [  09   Takeaways  ](#takeaways)

       The Problem With One Panel for Everything
-----------------------------------------

Most Filament tutorials show a single `AdminPanelProvider`. That works until you need a customer-facing portal sitting beside your internal admin, each with its own user model, guard, and middleware stack. Bolting both concerns onto one panel produces a tangled mess of policy checks and route conflicts.

The cleaner path: register two discrete panels, each owning its auth contract.

---

Registering a Second Panel
--------------------------

Filament resolves panels through service providers. Create a dedicated provider for each panel.

```bash
php artisan make:filament-panel customer

```

This scaffolds `app/Providers/Filament/CustomerPanelProvider.php`. Configure it independently:

```php
public function panel(Panel $panel): Panel
{
    return $panel
        ->id('customer')
        ->path('portal')
        ->authGuard('customer')          // dedicated guard
        ->login(CustomerLogin::class)    // custom login page
        ->colors(['primary' => Color::Teal])
        ->discoverResources(
            in: app_path('Filament/Customer/Resources'),
            for: 'App\\Filament\\Customer\\Resources'
        )
        ->middleware([
            EncryptCookies::class,
            VerifyCsrfToken::class,
            SubstituteBindings::class,
        ])
        ->authMiddleware([Authenticate::class]);
}

```

Register both providers in `bootstrap/providers.php` (Laravel 11+) or `config/app.php`.

### Separate Guards and User Models

```php
// config/auth.php
'guards' => [
    'web'      => ['driver' => 'session', 'provider' => 'users'],
    'customer' => ['driver' => 'session', 'provider' => 'customers'],
],
'providers' => [
    'users'     => ['driver' => 'eloquent', 'model' => App\Models\User::class],
    'customers' => ['driver' => 'eloquent', 'model' => App\Models\Customer::class],
],

```

Filament calls `auth()->guard($panel->getAuthGuard())` internally, so the panel's guard name is the only coupling point.

---

Sharing Resources Across Panels
-------------------------------

Occasionally an `OrderResource` belongs in both panels but with different column sets. Rather than duplicating the class, use a base resource and extend it:

```php
// App\Filament\Base\BaseOrderResource.php
abstract class BaseOrderResource extends Resource
{
    protected static string $model = Order::class;

    public static function baseColumns(): array
    {
        return [
            TextColumn::make('id')->sortable(),
            TextColumn::make('total')->money('usd'),
        ];
    }
}

// App\Filament\Admin\Resources\OrderResource.php
class OrderResource extends BaseOrderResource
{
    public static function table(Table $table): Table
    {
        return $table->columns([
            ...static::baseColumns(),
            TextColumn::make('customer.email'),
        ]);
    }
}

```

---

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

Filament tables call `paginate()` on the Eloquent builder. On a table with 500k rows, the default `COUNT(*)` for pagination becomes expensive fast.

### Override the Table Query

Scope the query at the resource level to avoid full-table scans:

```php
public static function getEloquentQuery(): Builder
{
    return parent::getEloquentQuery()
        ->select(['id', 'status', 'total', 'created_at', 'customer_id'])
        ->with('customer:id,email')   // eager-load only needed columns
        ->where('created_at', '>=', now()->subYear());
}

```

### Disable Count-Based Pagination

Filament v3 supports `->paginationPageOptions([25, 50])` but still fires a count query. For very large tables, switch to simple pagination:

```php
public static function table(Table $table): Table
{
    return $table
        ->paginated([25, 50])
        ->defaultPaginationPageOption(25)
        ->query(fn () => static::getEloquentQuery())
        // Filament respects simplePaginate when you override the paginator:
        ->paginateUsing(fn (Builder $query, int $page, int $perPage) =>
            $query->simplePaginate($perPage, ['*'], 'page', $page)
        );
}

```

### Index Your Sort Columns

Every sortable column fires an `ORDER BY`. Ensure composite indexes cover the sort + filter combination:

```sql
CREATE INDEX orders_status_created_at_idx ON orders (status, created_at DESC);

```

Run `EXPLAIN ANALYZE` in PostgreSQL or `EXPLAIN FORMAT=JSON` in MySQL to confirm the index is used.

---

Takeaways
---------

- Register each panel in its own provider with a dedicated auth guard and user model — never share guards between panels.
- Use abstract base resources to share schema logic without duplicating Eloquent models.
- Override `getEloquentQuery()` to select only required columns and constrain result sets before Filament paginates.
- Replace `paginate()` with `simplePaginate()` via `paginateUsing()` on high-volume tables to eliminate the expensive `COUNT(*)` query.
- Add composite indexes on every column combination used for filtering and sorting in your tables.

 Found this useful?

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

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

  3 questions  

     Q01  Can two Filament panels share the same Eloquent model with different guards?        Yes. The guard is configured on the panel, not the model. You can point both panels at the same User model but use different guards — though separate models per panel is cleaner when the authentication contracts differ. 

      Q02  Does overriding paginateUsing break Filament's built-in filter and sort state?        No. Filament applies filters and sorts to the Eloquent builder before the paginator runs. Swapping paginate() for simplePaginate() inside paginateUsing() only changes how the result set is sliced, not how the query is built. 

      Q03  How do I prevent a resource registered in one panel from appearing in another?        Use discoverResources() with panel-specific namespaces and directories. Resources discovered under App\Filament\Admin\Resources are invisible to the customer panel, which discovers from App\Filament\Customer\Resources. 

  Continue reading

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

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

 [ ![Streaming AI Responses in Laravel: Token Budgets, Structured Output, and Agent Contracts](https://cdn.msaied.com/584/3ffe135721c65ab3f9b40401dc3c41de.png) laravel ai llm 

### Streaming AI Responses in Laravel: Token Budgets, Structured Output, and Agent Contracts

Learn how to stream LLM responses in Laravel, enforce token budgets, and lock structured output to typed PHP c...

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

 23 Aug 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/streaming-ai-responses-in-laravel-token-budgets-structured-output-and-agent-contracts) [ ![Typed PHP 8.3 Enums as Eloquent Casts, Route Parameters, and Validation Rules](https://cdn.msaied.com/583/7301900aac0f2ec5d1347df11ce92188.png) laravel php8.3 enums 

### Typed PHP 8.3 Enums as Eloquent Casts, Route Parameters, and Validation Rules

Go beyond basic enum casting. Learn how to wire PHP 8.3 backed enums into Eloquent, route model binding, and c...

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

 23 Aug 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/typed-php-83-enums-as-eloquent-casts-route-parameters-and-validation-rules) [ ![Livewire v3 Lazy Components, Islands, and Deferred Loading in Practice](https://cdn.msaied.com/582/564b2d098d2b94b53d4f5319ac77d58b.png) livewire laravel performance 

### Livewire v3 Lazy Components, Islands, and Deferred Loading in Practice

Lazy components, islands, and deferred loading in Livewire v3 let you ship fast initial pages without sacrific...

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

 23 Aug 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/livewire-v3-lazy-components-islands-and-deferred-loading-in-practice-1) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.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://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.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)
