phattarachai/db-snapshot-sync-laravel

Rebuild a Laravel dev database from production in one command — driver-aware dump sanitizer, sync orchestrator, and a token-protected internal snapshot API. Extends spatie/laravel-db-snapshots.

Maintainers

Package info

github.com/phattarachai/db-snapshot-sync-laravel

pkg:composer/phattarachai/db-snapshot-sync-laravel

Transparency log

Statistics

Installs: 31

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.3 2026-08-15 11:27 UTC

This package is auto-updated.

Last update: 2026-08-15 11:27:33 UTC


README

Packagist Version Tests PHPStan License

Rebuild a Laravel developer's local database from production in one command. Extends spatie/laravel-db-snapshots with the three pieces every project otherwise reimplements: a driver-aware dump sanitizer, a sync orchestrator, and the token-protected internal API the source server exposes.

snapshot:sync --fresh
  → trigger a fresh dump on production (internal API)
  → download the .sql.gz
  → snapshot:sed  (strip directives that reject on a local client)
  → snapshot:load --drop-tables --force --stream

Supports PostgreSQL and MySQL/MariaDB.

Why

spatie/laravel-db-snapshots dumps and loads, but a dump made by a production pg_dump / mysqldump rejects on a developer's locally-installed client — psql meta-commands (\restrict, SET transaction_timeout), owner/grant lines, or MySQL DEFINER= clauses that need SUPER. This package strips those, and adds the download side so the whole "copy prod down to local" loop is one command instead of copy-pasted per project.

Install

composer require phattarachai/db-snapshot-sync-laravel
php artisan db-snapshot-sync:install

The installer publishes the config, writes the env keys (generating a token), and prints the source-side snippets you paste into config/db-snapshots.php, config/filesystems.php, config/database.php (dump exclusions) and the scheduler. It requires spatie/laravel-db-snapshots and a snapshots filesystem disk on both ends.

Commands

  • snapshot:sed {name?} {--latest} — sanitize a snapshot on the disk so it re-imports cleanly. Postgres mutates in place; MySQL writes a separate .sanitized.sql.gz.
  • snapshot:sync {--fresh} {--source=production} {--no-load} {--keep-raw} — pull the latest snapshot from a source, sanitize, and load into the local DB. Runs only in the environments listed in db-snapshot-sync.sync.allowed_environments.

Start with a dry run once the source URLs are set:

php artisan snapshot:sync --no-load     # download + sanitize, no DB clobber
php artisan snapshot:sync               # full sync from production

The source-side API

Set DB_SNAPSHOT_SYNC_API=true (and the shared INTERNAL_API_TOKEN) on production/UAT to expose:

Method Route Purpose
GET /internal/snapshots list servable snapshots
POST /internal/snapshots create a fresh one synchronously (--fresh)
GET /internal/snapshots/latest stream the newest download

EnsureInternalToken 404s the whole group in local and checks a hash_equals bearer token otherwise; the routes carry throttle:5,1. The consumer sends the matching token from its .env.

Configuration

config/db-snapshot-sync.php covers the disk name, token, source URLs, snapshot:load flags, the per-driver sanitizer rules (add a prefix/sed expression when a new dump quirk appears), and the API's reject-list (never serve a schema-only baseline or a .sanitized. intermediate).

dump.exclude_table_data lists framework caches and transient queues (cache, sessions, jobs, pulse_*, telescope_*, …) whose data is skipped when the source builds a sync snapshot — the schema is still dumped, and a project's own rollback snapshots are untouched. This keeps the dev copy small; real domain tables are always included. The Postgres sanitizer streams the dump line-by-line, so a multi-GB snapshot sanitizes without loading the whole file into memory.

dump.rows_per_insert (default 1000) batches the sync snapshot into multi-row INSERTs. laravel-db-snapshots forces --inserts because its loader restores through PDO (which can't stream COPY), so a large table otherwise restores one round-trip per row — a million-row table can take tens of minutes. Batching cuts that to a couple of statements' worth of work. Applies to the sync snapshot only; the committed baseline stays single-row so it keeps diffing line-by-line.

Testing

composer test

License

MIT. See LICENSE.md.