DEV Community

Cover image for PagibleAI: A Cloud-Native Laravel CMS, Not Just a Container
Aimeos
Aimeos

Posted on

PagibleAI: A Cloud-Native Laravel CMS, Not Just a Container

A container changes how software is packaged. It says little about where that software keeps state or how it behaves when another instance comes online.

A CMS that writes uploads to local disk, caches pages inside one process and runs background work during web requests is still tied to one machine, however neatly it has been containerized.

The Cloud Native Computing Foundation defines cloud-native systems in terms of scalability, loose coupling, resilience, manageability and observability. It cites containers and microservices among the techniques used to achieve those properties.

PagibleAI CMS follows that model through Laravel's infrastructure contracts. Database connections, filesystem disks, cache stores, queues and broadcasting form the boundary between the CMS and the machine running it.

A site can begin with SQLite and local files, then move to replicated application nodes, a managed database, object storage, shared cache and independent queue workers without altering its content model.

“Fully cloud-native” here means that the CMS has no architectural dependency on a particular web server. Kubernetes is one possible runtime, not a requirement.

One application, one operating model

PagibleAI installs as a Composer package:

composer require aimeos/pagible
php artisan cms:install
php artisan migrate
Enter fullscreen mode Exit fullscreen mode

Installation turns an existing Laravel application into the CMS. It does not introduce a separate content service with its own authentication, deployment and monitoring model.

PagibleAI uses the application's service container, Eloquent connections, authentication, middleware, filesystem disks, cache stores, queues and logging channels. Development and operations stay within the Laravel stack.

Laravel serves as both the framework beneath the admin panel and the infrastructure abstraction layer.

Clients → CDN → Load balancer → Laravel replicas
                                  ├── Managed database
                                  ├── Redis cache and locks
                                  ├── Object storage
                                  └── Queue broker → workers
Enter fullscreen mode Exit fullscreen mode

The same topology can run on AWS, Google Cloud, Azure, Kubernetes, conventional virtual machines or a managed Laravel platform. Provider-specific details remain in Laravel's configuration.

Durable state stays off the web node

Horizontal replication only works when the next request can land on any node. PagibleAI keeps durable state in shared infrastructure rather than in the web process.

Content in the database

Pages, reusable elements, files and versions are Eloquent models. PagibleAI supports SQLite for a compact local installation and MySQL, MariaDB, PostgreSQL or SQL Server for production deployments.

Every edit creates an immutable version snapshot. Editors work against the latest version while visitors receive the published one. Any replica can serve either view because the database, rather than the PHP process, owns that state. Laravel's read/write connections can place a managed primary and replicas behind the same CMS connection without introducing another database layer.

Media on a filesystem disk

PagibleAI sends uploads through Laravel's filesystem abstraction. The default public disk is convenient on a laptop, while CMS_DISK=s3 can move the same media operations to Amazon S3 or another S3-compatible service. Laravel's filesystem drivers also cover services such as Cloudflare R2, MinIO and DigitalOcean Spaces.

Uploaded media is then independent of the web-container lifecycle. Replacement nodes need no copied volume, and a CDN can serve files without routing every byte through PHP.

Cache and coordination

PagibleAI's public page cache stores complete HTML responses. In a multi-node deployment, that cache moves from the default file store to a shared, lock-capable store such as Redis.

The lock matters as much as the cached HTML. When a popular page expires, one renderer acquires the lease. Other requests can receive the stale entry during a short revalidation window instead of repeating the same query and rendering work across every replica.

Fresh responses carry shared-cache directives such as s-maxage, allowing a CDN to absorb public traffic before it reaches the application. Requests with a Laravel session or an Authorization header bypass the public cache, so authenticated content is not accidentally promoted to a shared response.

After a publication, deletion or access change commits, PagibleAI queues targeted invalidation work. If that job is delayed, the configured cache lifetime determines how long an old response can remain available.

Commit first, then distribute

Database writes and distributed side effects fail independently. An event emitted before commit may describe a change that later rolls back; a cache or search job may run after a temporary queue failure.

PagibleAI starts these side effects after the database transaction commits:

  • Search reconciliation is dispatched only after the content transaction succeeds.
  • Rendered-page invalidation is requested after commit and handled by a queue worker.
  • Collaboration events are emitted after commit, so another editor never receives a change that the database later rejects.

Clients, caches and search indexes therefore do not observe writes that the database later rejects.

The jobs use Laravel's queue contract, so production can use Redis or Amazon SQS while development stays on a simpler connection. Workers scale independently from the web tier, with Laravel supplying retries, failed-job handling, supervision and deployment restarts.

Built-in search, external engine optional

PagibleAI's Laravel Scout engine uses the full-text facilities already present in the selected database:

  • FTS5 on SQLite
  • MATCH ... AGAINST on MySQL and MariaDB
  • tsvector on PostgreSQL
  • CONTAINSTABLE on SQL Server

Draft and published content receive separate index rows, preserving the same visibility boundary used by the CMS.

The first production deployment therefore needs no separate search cluster. If a later workload justifies an external engine, Laravel Scout remains the extension point.

Headless and server-rendered delivery

Content is available through three delivery surfaces:

  • A GraphQL administration API, used by the Vue editor and available to custom tools
  • A read-only JSON:API for web applications, mobile clients and static-site pipelines
  • Server-rendered Blade themes for sites that benefit from direct HTML delivery

All three use the same content model. The editor and GraphQL endpoint can remain inside a private application network, the read-only API can sit behind an API gateway, and Blade output can be cached at the edge. Frontend delivery can scale independently without maintaining a second copy of editorial data.

Tenant context beyond the HTTP request

PagibleAI uses single-database multi-tenancy. CMS models carry a tenant_id, and a global Eloquent scope limits queries to the active tenant. Multi-domain routing can map separate page trees to separate domains.

Search jobs retain the tenant they were created for. Page-cache keys include the tenant and domain. Realtime channels require both a matching tenant and the relevant view permission.

That gives SaaS products and agencies one deployment and one shared database with application-level content isolation. It is not database-per-tenant isolation. Requirements that mandate a separate database for every customer need a different tenancy architecture.

Realtime and long-running processes

When broadcasting is enabled, PagibleAI uses Laravel Reverb and Echo to notify other editors about saved, published, restored, moved or deleted content.

The events carry the metadata needed to update a list. They do not turn the WebSocket connection into a second content-delivery API. An open detail view re-fetches changed content through GraphQL, and a client reloads its state after reconnecting because it may have missed events while the socket was unavailable.

Laravel Octane and queue workers keep the application alive between requests or jobs. PagibleAI binds tenant and access state to scoped lifetimes, keeps GraphQL metadata on the request, and avoids a global user-ID permission cache. This prevents state from one execution leaking into the next under Octane.

Optional Pulse metrics cover page requests, search, contact forms, JSON:API, GraphQL and MCP operations. Structured watch logs use the application's logging stack, while Laravel's health route can feed a load balancer or Kubernetes probe.

Configuring a distributed deployment

PagibleAI's local defaults suit a single process. A distributed deployment replaces the node-local parts with shared services.

Concern Small installation Distributed installation
Content SQLite Managed MySQL, MariaDB, PostgreSQL or SQL Server
Media Local public disk S3-compatible object storage and CDN
Page cache and locks File cache Shared Redis cache
Sessions Local or database Shared database or Redis
Jobs Synchronous or database queue Redis or SQS with independent workers
Web runtime One PHP process Replicas behind a load balancer
Live updates Disabled Reverb with shared production configuration
Telemetry Local logs Centralized logs and optional Pulse metrics

A production environment may begin like this:

DB_CONNECTION=pgsql
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis

CMS_DISK=s3

# After installing and configuring Laravel Reverb
CMS_BROADCAST=true
Enter fullscreen mode Exit fullscreen mode

The complete-page cache selects its own store, so configure Redis explicitly for production:

// config/cms/theme.php
'cache' => env('APP_DEBUG') ? 'array' : 'redis',
Enter fullscreen mode Exit fullscreen mode

The infrastructure also needs a few standard operating rules:

  1. Build application code, Composer dependencies and published assets into an immutable release.
  2. Keep uploaded media off ephemeral web disks.
  3. Run queue workers separately, restart them during deployments and run only one scheduler.
  4. Ensure the CDN bypasses public HTML caching for session and authorization requests.
  5. Extend Laravel's health endpoint with database and cache diagnostics appropriate to your availability target.

PagibleAI uses Laravel's cache API, queues and filesystem directly, so the same operational tooling applies to the CMS and the rest of the application.

The source is available in the PagibleAI GitHub repository, and the installation guide covers the first deployment.

What PagibleAI leaves to the deployment

PagibleAI does not provision a VPC, tune PostgreSQL, choose a Redis topology or write Kubernetes manifests. The deployment team owns those choices.

They remain deployment responsibilities. PagibleAI keeps them outside the content model and editorial workflow, allowing state to move to managed services, workers to split from the web tier and public responses to move toward the edge.

The visible product includes structured content, versioning, AI-assisted editing, GraphQL, JSON:API and MCP tools. The deployment model rests on less visible choices: authoritative database state, replaceable storage, shared cache coordination, post-commit side effects, queued work and request isolation in long-running processes.

The same PagibleAI CMS package and content model can run in one process or across a cluster.

Top comments (0)