Laravel SaaS Foundation on PostgreSQL
A pragmatic Laravel SaaS baseline using Laravel’s application capabilities for authentication, PostgreSQL for relational data, a transactional email provider, and containerized deployment on general cloud infrastructure. Managed identity is intentionally not selected because Laravel can implement application-owned authentication; adding an external identity provider remains optional.
Executable examples and validation
No executable package has been validated for this architecture yet. The implementation sequence below is guidance, not a tested repository.
Validation badges are scoped to specific artifacts and recorded tests. They never certify a full stack unless that scope was actually tested.
Architecture and implementation
Architecture
Run the Laravel application as a containerized web process behind Nginx on cloud infrastructure. Persist tenants, users, subscriptions or domain records, application data, transactional outbox records, and verified webhook-event records in PostgreSQL. Use Laravel's authentication, authorization, email, queue, migration, and scheduling facilities within the application. Deliver transactional email through Postmark. Store source and deployment configuration in GitHub, and use Docker to establish consistent build and runtime packaging. Use S3 for user-uploaded objects and backups where object storage is appropriate. Add Redis for cache, session, rate-limit, and queue coordination only if the SaaS workload needs these shared services. Treat outbound-provider request idempotency and inbound webhook-event deduplication as separate controls.
Implementation sequence
- Create a Laravel application with a clear tenant model, authenticated-user model, role or policy rules, tenant-scoped query conventions, and database migrations targeting PostgreSQL.
- Implement registration, login, password reset, email verification, session handling, and authorization using Laravel facilities; apply server-side tenant isolation to every tenant-owned read and write path.
- Enforce account and membership status on authenticated requests and state-changing actions. Define session revocation behavior: deny access on the next server-side status check, refresh or invalidate sessions when possible, and reconcile delayed identity or event changes; do not assume instantaneous disabling.
- Define a PostgreSQL schema with foreign keys, uniqueness constraints, indexes, audit-relevant timestamps, and explicit ownership relationships. Include durable outbox and webhook-event tables with stable identifiers and processing-state fields.
- Create outbound messages and their outbox records in the same database transaction as the business change. Use pending, sending, sent, unknown, and error states; retain a stable application message identity and provider message identifier when available.
- Send outbox records through workers with crash-safe claiming and retry rules. A timeout after transmission becomes unknown, not failed; reconcile by provider message ID or supported idempotency or delivery-event capabilities where available. If lookup and provider deduplication are unavailable, document at-least-once delivery, potential duplicates, and an operator resolution path.
- Configure Postmark as the transactional mail transport and create templates for account verification, password recovery, security notifications, and operational failure handling. Use a verified sender identity. Treat provider acceptance and recipient delivery as distinct outcomes.
- If mail webhooks are enabled, verify provider authenticity using the provider-supported mechanism over the raw request before trusting payload fields; separately verify the applicable mechanism rather than assuming one. Reject or quarantine unverified events without changing application state.
- For verified webhook events, persist the provider event identifier under a uniqueness constraint before processing. Atomically claim work with an in-progress state and recoverable lease, apply state or entitlement changes and completion status transactionally, and make duplicate delivery or post-claim crashes retryable without incorrectly marking the event complete.
- Containerize the Laravel runtime and supporting worker process if asynchronous jobs are used. As a deployment prerequisite, select and document how workers and Laravel scheduled commands are continuously invoked, restarted, monitored for liveness and backlog, and manually or automatically recovered after failure.
- Provision the application host, PostgreSQL service, Nginx reverse proxy, TLS certificate automation, and restricted network paths. Run migrations through a controlled release procedure with rollback planning.
- Use Amazon S3 for uploads and encrypted backup artifacts. Define object lifecycle, retention, restore testing, and tenant-data deletion behavior before accepting customer data.
- Add Redis only if shared cache, sessions, rate limiting, or asynchronous Laravel queues are required; configure application fallback and recovery behavior for Redis outages.
- Maintain code, infrastructure definitions, and documented deployment procedures in GitHub. Require review and protected handling for production configuration changes.
- Instrument application errors and operational logs through the chosen hosting and application mechanisms; establish health checks, worker and scheduler monitoring, database backup monitoring, mail-outbox and webhook-processing monitoring, and periodic restoration exercises.
Security and operations
- Use Laravel authorization policies and middleware in addition to authentication; authentication alone does not establish SaaS tenant isolation. Enforce tenant-scoped authorization server-side for every state change.
- Treat tenant identifiers supplied in URLs, forms, and APIs as untrusted. Derive tenant context from validated membership and scope database queries accordingly.
- Hash passwords using Laravel-supported password hashing, require email verification where appropriate, rotate sessions after authentication events, and protect login and reset endpoints with rate limiting.
- Store database, S3, mail, and deployment credentials only in secret-management or deployment configuration. Do not commit secrets, backup keys, or production environment files to GitHub.
- Enforce TLS from the public endpoint to the reverse proxy. Restrict PostgreSQL and Redis to private network access; do not expose them directly to the public internet.
- Use least-privilege database credentials. Separate migration or administrative credentials from the runtime application account where operationally practical.
- Protect object storage with narrowly scoped credentials, private-by-default objects, server-side authorization checks, and time-bounded access URLs when direct client access is needed.
- Encrypt backup artifacts, define retention and access controls, and regularly test restoration to a separate environment. Backups should cover PostgreSQL data and required uploaded objects.
- For webhook flows, authenticate the raw request with the provider-supported verification mechanism before parsing or trusting payload fields. Persist and deduplicate verified provider event identifiers; unauthenticated or malformed events must not alter application state.
- Use transactional state transitions, unique constraints, and recoverable work claims for outbox and webhook processing. Do not mark sends, events, or entitlement updates complete before their required database effects are durable.
- Keep sensitive customer data out of email subjects, logs, queue payloads, raw webhook retention where unnecessary, and exception reports. Keep container base images and PHP dependencies maintained, review dependency changes, and make release changes through an auditable process.
Limitations
- The catalogue identifies PostgreSQL but does not identify a specific managed PostgreSQL offering, container orchestration system, PHP-FPM runtime, secret manager, CI/CD execution service, worker supervisor, or scheduler. Those deployment and recovery details require separate selection and validation before operation.
- Laravel is capable of application-owned authentication, but the catalogue does not identify a Laravel-specific starter kit or package; the exact implementation choices are outside this stack recommendation.
- This stack does not include billing. Add a payment provider only when subscription collection, invoicing, tax handling, or entitlement synchronization is in scope.
- Redis is optional and introduces additional operational responsibility when self-hosted or separately managed.
- A single cloud provider and a single object-storage target do not provide automatic multi-region disaster recovery. Recovery objectives and replication requirements must be defined separately.
- Email provider setup requires domain and sender verification outside the application; deliverability depends on operational configuration and message practices.
- Provider acceptance is not recipient delivery. Where the provider cannot support idempotent submission or message-status lookup, outbound retries are at-least-once and can produce duplicates; unresolved unknown outcomes require documented operator review.
- Session revocation can be delayed until the application's configured server-side status check, session refresh, or expiry mechanism takes effect; immediate disabling requires a separately enforced mechanism.
Alternatives to consider
- Use MySQL (product 32) instead of PostgreSQL where existing operational expertise or application constraints favor it.
- Use Resend (product 11) or SendGrid (product 13) instead of Postmark for transactional email after validating sender, delivery, compliance, and integration needs.
- Use Hetzner Cloud (product 49) or GreatHosts (product 50) instead of DigitalOcean for infrastructure hosting.
- Use Backblaze B2 (product 53), Cloudflare R2 (product 52), or Wasabi Hot Cloud Storage (product 95) in place of Amazon S3 for object storage and backup targets.
- Add Auth0 (product 42), Clerk (product 43), or self-hosted Keycloak (product 41) if externalized identity, federation, or centralized identity administration is required.
- Add Sentry (product 56) for error and performance monitoring, and OpenTelemetry (product 99) with Prometheus (product 100) and Grafana (product 57) when a defined observability operating model justifies the additional services.
A reference architecture, not a tested deployment or guarantee of interoperability. Validate all external contracts, versions and prices before implementation.
Sources and review dates
Official pages are recorded with UTC retrieval timestamps. Retrieval confirms access to a page, not verification of every technical claim, price, or license.