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: 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%2Fmsaied.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%2Fmsaied.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://msaied.com/articles) 

 [ ![Contextual Macros and Mixins: Extending Laravel Collections Without Bloat](https://cdn.msaied.com/556/0c5a2892229d005cb3b747c868df5bb6.png) laravel collections macros 

### Contextual Macros and Mixins: Extending Laravel Collections Without Bloat

Learn how to add domain-specific behaviour to Laravel's Collection class using macros, mixins, and higher-orde...

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

 16 Aug 2026     3 min read  

  Read    

 ](https://msaied.com/articles/contextual-macros-and-mixins-extending-laravel-collections-without-bloat) [ ![Modular Monolith in Laravel: Enforcing Bounded Contexts Without a Microservice Tax](https://cdn.msaied.com/555/c194fc79e9397fef3bcd3a896eb558fd.png) laravel architecture ddd 

### Modular Monolith in Laravel: Enforcing Bounded Contexts Without a Microservice Tax

Learn how to carve a Laravel application into cohesive bounded contexts using modules, internal contracts, and...

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

 16 Aug 2026     3 min read  

  Read    

 ](https://msaied.com/articles/modular-monolith-in-laravel-enforcing-bounded-contexts-without-a-microservice-tax) [ ![Octane Worker Lifecycle, State Leakage, and Memory Management in Production](https://cdn.msaied.com/554/8cc265358b47e59601a66d1e247eba9a.png) laravel octane performance 

### Octane Worker Lifecycle, State Leakage, and Memory Management in Production

Laravel Octane keeps workers alive across requests, which means static state, resolved singletons, and stale d...

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

 16 Aug 2026     3 min read  

  Read    

 ](https://msaied.com/articles/octane-worker-lifecycle-state-leakage-and-memory-management-in-production-2) 

   [  ![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)
