Fermin Perdomo

Senior Full Stack Engineer | PHP | JavaScript

Realtime dashboard with Firebase and Laravel API

Fermin Perdomo
October 26, 2025

Why a Realtime dashboard with Firebase and Laravel API matters

Building a Realtime dashboard with Firebase and Laravel API helps teams see changes the instant they happen. Think orders per minute, vehicles on a map, live inventory, or support tickets. Traditional reporting stacks batch data. That’s fine for end-of-day summaries, but not for reacting in seconds. Laravel gives you a familiar, productive backend with clean routing, validation, and queues. Firebase delivers low-latency streaming, scalable storage, and battle-tested auth. Together, they’re a practical pairing: Laravel handles business logic and integrations; Firebase pushes live updates to users without you writing socket servers from scratch.

You’ll also get portability. If your sources include webhooks (Stripe, Shopify), IoT publishers, or internal microservices, a Laravel API is an easy landing zone. From there, the API standardizes payloads, enforces rules, and publishes events to Firebase. On the client, a lightweight web app subscribes to Firebase listeners and renders charts, tables, and alerts in real time. This guide walks through architecture, modeling, security, performance, testing, deployment, and cost control—so your dashboard is fast today and still fast when traffic spikes tomorrow.

Architecture at a Glance

High-level flow. Clients send data to your Laravel API (or receive data from third-party webhooks). Laravel validates and transforms payloads, persists authoritative records (e.g., in MySQL/Postgres), and then broadcasts sanitized summaries into Firebase. The frontend subscribes to Firebase collections/paths and updates instantly—no manual refresh. This keeps the “write” path trusted and the “read” path blazing fast.

Firestore vs Realtime Database vs Pub/Sub.

  • Cloud Firestore: flexible, strongly consistent queries, great indexing, hierarchical documents—ideal for dashboards with filters (e.g., site, region, product).
  • Realtime Database: simple JSON tree and ultra-low latency—ideal for high-frequency counters or presence.
  • Pub/Sub & Functions: for heavy fan-out or async enrichment (e.g., anomaly scoring), use Pub/Sub triggers to compute aggregates and write back to Firestore.

Sockets and queues. Use Laravel queues to decouple ingestion from broadcast. You can still keep Laravel Echo for internal channels, but Firebase listeners generally replace custom websockets for cross-platform clients.

Project Setup and Tooling

Laravel installation & env.
Create a fresh Laravel app, set up your database, and add queue drivers (Redis/SQS). Configure API rate limiting and API authentication (Sanctum for first-party SPAs, Passport for third-party clients). Keep secrets in .env and never commit them.

composer create-project laravel/laravel dashboard
php artisan key:generate
php artisan migrate

Firebase project & SDKs.
Create a Firebase project, enable Authentication (Email/Password, SSO, etc.), choose Cloud Firestore or Realtime Database, and download a server service account JSON for Laravel. On the client, use web SDKs to subscribe to real-time data.

Local emulators.
Run Firebase Emulators for Auth, Firestore, and Functions during development. For webhook testing from third parties, expose Laravel via ngrok and point external services to your tunnel.

Data Modeling for Live Dashboards

Events and entities.
Dashboards thrive on events (order_placed, device_online, ticket_created) tied to entities (user, device, store). Store authoritative data in your SQL database for transactions and history. For the dashboard, project read-optimized views into Firebase.

Firestore structure.
Use collections like organizations/{orgId}/events, metrics/{orgId}/hourly, and widgets/{orgId}/kpis. Place hot widgets (like totals) in small docs that change frequently, and historical charts in partitioned collections (daily, hourly) to reduce write contention. Precompute top lists (e.g., “Top 10 products by revenue last hour”) and store them in dedicated docs to avoid expensive client-side sorting at scale.

Denormalization.
Don’t be afraid to duplicate data for speed—as long as you define a single writer. Use Cloud Functions or Laravel jobs to fan-out updates so widgets stay in sync.

Authentication & Authorization

Choosing an auth path.
For public dashboards or mobile clients, Firebase Authentication is convenient and secure. For server-to-server or partner integrations, use Laravel tokens (Sanctum/Passport). If both are needed, verify Firebase ID tokens inside Laravel for API calls.

Verifying Firebase tokens in Laravel (PHP):

use Kreait\Firebase\Factory;
use Firebase\Auth\Token\Exception\InvalidToken;

$factory = (new Factory)->withServiceAccount(config('services.firebase.credentials'));
$auth = $factory->createAuth();

try {
    $verifiedIdToken = $auth->verifyIdToken($idToken);
    $uid = $verifiedIdToken->claims()->get('sub');
    // Map uid to your local user/roles
} catch (InvalidToken $e) {
    abort(401, 'Invalid ID token');
}

Roles and claims.
Store roles in your SQL database and mirror key claims in Firebase custom claims to enforce Security Rules (“only users with role=manager can read org widgets”).

Ingesting Data with the Laravel API

Validation & rate limits.
Every ingest route should validate payloads, enforce idempotency keys, and apply rate limits per token or IP to shield your backend from spikes.

Example Controller (simplified):

// routes/api.php
Route::post('/events', [EventController::class, 'store'])->middleware('auth:sanctum');

// app/Http/Controllers/EventController.php
public function store(StoreEventRequest $request) {
    $event = Event::create($request->validated());
    dispatch(new \App\Jobs\BroadcastEventToFirebase($event->id));
    return response()->json(['ok' => true]);
}

Broadcast job to Firebase:

use Kreait\Firebase\Factory;

class BroadcastEventToFirebase implements ShouldQueue {
    public function __construct(public int $eventId) {}
    public function handle() {
        $event = Event::findOrFail($this->eventId);

        $db = (new Factory)
            ->withServiceAccount(config('services.firebase.credentials'))
            ->createFirestore()
            ->database();

        $ref = $db->collection('organizations')
                  ->document($event->org_id)
                  ->collection('events')
                  ->document((string)$event->id);

        $ref->set([
            'type' => $event->type,
            'amount' => $event->amount,
            'createdAt' => new \Google\Cloud\Core\Timestamp($event->created_at),
        ]);

        // Optionally update a hot KPI doc too
        $db->collection('widgets')->document($event->org_id)->set([
            'ordersPerMinute' => FieldValue::increment(1),
        ], ['merge' => true]);
    }
}

Realtime Updates to the Frontend

Direct Firebase listeners (React example):

import { useEffect, useState } from 'react';
import { getFirestore, collection, query, orderBy, limit, onSnapshot } from 'firebase/firestore';
import { initializeApp } from 'firebase/app';

const app = initializeApp({ /* your client config */ });
const db = getFirestore(app);

export default function LiveFeed() {
  const [events, setEvents] = useState([]);

  useEffect(() => {
    const q = query(
      collection(db, `organizations/${ORG_ID}/events`),
      orderBy('createdAt', 'desc'),
      limit(20)
    );
    const unsub = onSnapshot(q, (snap) => {
      setEvents(snap.docs.map(d => ({ id: d.id, ...d.data() })));
    });
    return () => unsub();
  }, []);

  return <ul>{events.map(e => <li key={e.id}>{e.type} · {e.amount}</li>)}</ul>;
}

Pagination & offline. Use startAfter for infinite scroll and enable persistence on the web SDK for offline caching. For charts, subscribe to an aggregate doc (e.g., metrics/{orgId}/hourly) and redraw when values change—no polling.

Caching, Aggregations, and Performance

Hot vs cold aggregates.
“Hot” widgets (live totals, counters) should be small docs updated frequently with atomic increments. “Cold” widgets (hourly/daily charts) are updated on schedule by Laravel jobs or Cloud Functions. This dual strategy controls costs and keeps writes predictable.

Indexes & composite queries.
In Firestore, define composite indexes for common dashboard filters (org + date range + status). Avoid “chatty” listeners—prefer fewer, focused subscriptions. If one page needs many lists, consider building a single dashboard document containing all widget summaries to minimize reads.

Security & Compliance

Security Rules.
Write least-privilege rules that check request.auth != null, enforce org boundaries, and verify custom claims. Example (Firestore):

// Only allow users with matching org and role=manager to read widgets
match /organizations/{orgId}/widgets/{docId} {
  allow read: if request.auth.token.orgId == orgId
              && request.auth.token.role == 'manager';
  allow write: if false;
}

Secrets & PII. Keep service accounts in secure key stores and never store sensitive PII in Firebase unless rules, encryption, and data retention meet your compliance needs. Add audit logs for every admin action in Laravel.

Observability

Instrument your Laravel API with structured logs (request IDs, org IDs, latency) and connect to a log aggregator. Add traces around hot paths (ingest → queue → Firebase write). In Firebase, enable usage dashboards and set alerts on sudden read/write spikes. For frontends, track client error rates and listener failure counts.

Testing Strategy

  • Unit tests for validators and transformers.
  • Feature tests for API routes with Sanctum/Passport.
  • Contract tests that assert Firebase documents are written in the right shape.
  • Emulator tests using the Firebase Emulator Suite so you can run CI without touching production.
public function test_event_broadcasts_to_firestore() {
    // Seed an event, run job, then assert via emulator client
    $this->artisan('queue:work --once');
    $doc = $this->firestore()->collection('organizations')->document($orgId)
        ->collection('events')->document($eventId)->snapshot();
    $this->assertTrue($doc->exists());
}

Deployment & CI/CD

Use environment-per-project (dev, staging, prod) in Firebase and separate Laravel .env files. CI runs tests, lints code, compiles assets, and deploys to your platform (Forge, Vapor, Docker on ECS). For the frontend, deploy a static build (Vite/Next) and point it to your Firebase project. For risk-free updates, prefer blue-green or canary deploys and version your Security Rules alongside code.

Cost Optimization

  • Reduce read fan-out by consolidating widget data into one doc per dashboard view.
  • Control writes with batching and atomic increments instead of replacing entire docs.
  • TTL policies: move old events to cold storage (SQL, BigQuery) and keep only recent summaries in Firebase.
  • Index wisely: each composite index costs storage; create only what you query.
  • Mitigate hot documents by sharding counters (e.g., 10 shards) and summing on read.

Common Pitfalls & How to Fix Them

  • N+1 listeners: too many subscriptions per page. Fix by bundling widgets in a single summary doc.
  • Over-broadcasting: pushing every field change. Fix by only updating denormalized, read-heavy fields.
  • Unbounded queries: missing limit and orderBy. Fix by always constraining and paginating.
  • Weak rules: broad allow read, write: if true. Fix by using claims and organization checks.
  • No idempotency: duplicate webhooks. Fix by storing event_id and enforcing uniqueness.

FAQs: Realtime dashboard with Firebase and Laravel API

1) Can I use both Firestore and Realtime Database?
Yes. Many teams store time-series and filtered lists in Firestore, and ultra-hot counters or presence in Realtime Database. Keep writers authoritative and document the sync strategy.

2) Is Laravel Echo still needed?
Often no. Firebase listeners can replace custom websocket infrastructure for client updates. Keep Echo for internal admin channels if you already rely on it.

3) How do I secure the dashboard for multi-tenant orgs?
Use Firebase custom claims with orgId and role. Enforce org boundaries in Security Rules and mirror checks in Laravel middleware.

4) What about analytics over months or years?
Archive detailed events in SQL or BigQuery and precompute rolling aggregates for the dashboard. Don’t stream the entire history to the client.

5) How do I test without billing surprises?
Use the Firebase Emulator Suite for Auth, Firestore, and Functions. Point your local app to the emulator hosts in .env.

6) Can I integrate third-party webhooks (Stripe, Shopify, IoT)?
Yes. Terminate webhooks at Laravel, validate signatures, transform payloads, and dispatch jobs that write summarized data to Firebase for instant UI updates.

Conclusion & Next Steps

A Realtime dashboard with Firebase and Laravel API lets you ship fast, stay secure, and scale smoothly. Laravel handles ingestion, validation, and business rules; Firebase delivers low-latency updates to every user. With thoughtful data modeling, strict Security Rules, and smart aggregates, your dashboard stays responsive and cost-efficient—even as traffic grows. Your next steps: set up your Laravel API, create your Firebase project, define your schema, and wire up listeners in your frontend. Then iterate with observability, tests, and CI/CD until releases are boring and dashboards feel instant.

Helpful resources:


Reactions

Loading reactions...
Log in to react to this post.

Comments

Please login to leave a comment.

Newsletter