Skip to content

Adopt Pulsar in an existing application

You will add one bounded Pulsar slice to a supported Laravel application without moving its existing code. Establish a tested checkpoint first, stop if the installer cannot patch safely, and keep the previous commit as the rollback boundary.

Before you begin

First confirm Pulsar fits the application and choose the slice. Work from the application root on a dedicated branch. You need a passing regression test for the legacy behavior, a clean commit, a reviewed data backup and reversal procedure, and collision-free names for the new slice.

This walkthrough targets the current published Pulsar v0.4.1 package on supported Laravel 12 or 13. It adds the accepted Client Orders feature beside a representative legacy Orders route. Replace the legacy names with evidence from your application; do not copy them mechanically.

Keep each concern in its home

Existing concernDefault home and coexistence ruleA new or deliberately migrated Pulsar slice
RoutesExisting routes/*.php definitions, URLs, names, and middleware remain.New API routes live in the generated Service route file. make:service --web may provide an unprefixed browser route file for a later deliberate migration. Never register two routes with the same method and URI, or reuse a route name.
ControllersExisting App\Http\Controllers classes remain while their routes remain.A new or parity-proven migrated delivery class lives under its Service Module. Delete the old class only after route and response parity.
Form RequestsExisting App\Http\Requests classes stay with legacy Controllers.A new Request for the Pulsar route lives in the Service Module. Do not use a shared Request as a hidden bridge between workflows.
ModelsLegacy App\Models types remain for legacy behavior.A new bounded entity lives in its Domain. Move an existing Model only for a required Pulsar dependency edge with safely migrated callers.
MigrationsAll migrations remain in database/migrations.New schema also uses a stock timestamped Laravel migration.
FactoriesAll factories remain in database/factories.Add or adapt one only when the new tests need it.
SeedersAll seeders remain in database/seeders.Keep orchestration in stock seeders and call bounded factories explicitly.
ConfigurationApplication configuration remains in config.Read configuration at the appropriate Laravel edge; do not invent app/Pulsar/Config.
Application providersExisting App\Providers classes and registrations remain.Installer adds PulsarServiceProvider; generated Service providers stay under their Services and receive one explicit provider-list entry.
Bootstrapbootstrap/app.php and bootstrap/providers.php remain Laravel-owned seams.Accept only reviewed installer edits, keep its backup, and stop on an unsafe custom-bootstrap refusal.
TestsExisting tests remain under tests.Add public-boundary tests under that stock tree; Pulsar does not generate migrations or tests.
New Services, Modules, and DomainsNo stock home is renamed merely to make room.New Pulsar architecture lives under app/Pulsar. Create only what the slice needs.

Checkpoint 0: Establish the recovery boundary

  1. Begin from a clean, reviewed application commit. Stop if unrelated work cannot be separated.
  2. Back up production data with the application's established procedure and record how the new migration will be reversed. Do not assume a migration batch number.
  3. Run the targeted legacy test and relevant suite. Record its route method, URI, name, handler, response, schema, provider binding, and provider/bootstrap registrations.
  4. Inventory collisions for app/Pulsar, PulsarServiceProvider, Client, Orders, every intended class, the new route, orders table, and migration name.
  5. Confirm supported PHP/Laravel/Composer and the current package boundary. Stop for v0.3 or an unexplained package reference and complete the package-specific upgrade first.

The commit plus reviewed data plan is the rollback boundary. The installer backup is evidence for one bootstrap file; it is not application-wide recovery.

Checkpoint 1: Require and preview

Run the project-local Composer require described in Install Pulsar. Composer changes composer.json, composer.lock, and vendor, which is why Checkpoint 0 comes first. Confirm require-dev contains ^0.4.1 and the lock selects v0.4.1 at source and distribution reference fc14af65381c9bcd7fc99b05f893cef0344dad54. Stop on drift.

Run vendor/bin/pulsar install --dry-run. It must exit 0, describe only the application provider and bootstrap seams, and leave every application file unchanged. Review the proposed diff. An unknown custom bootstrap, conflicting provider, unexpected path, or unreviewed edit is a stop—not permission to use --force blindly.

Checkpoint 2: Install and prove coexistence

Run vendor/bin/pulsar install, inspect the provider/bootstrap edits and backup, then rerun it. The second run must report no changes. Before generating a Service, repeat the unchanged legacy test and route inspection.

Generate Client only if its name is collision-free, register one provider entry in bootstrap/providers.php, and confirm the application boots. Repeat the legacy test, route, response, schema, config marker, provider binding, and source checks. Any change is a stop.

Checkpoint 3: Add one bounded slice

Follow the exact generators and implementation in Build your first Pulsar feature. The new POST /api/client/orders route named client.orders.store does not replace the legacy GET|HEAD /legacy/orders/{legacyOrder} route named legacy.orders.show. The new orders migration, public HTTP tests, and Pulsar types are additive; do not copy the legacy Controller, Request, Model, or provider merely to make the tree uniform.

Run the new feature tests and relevant suite. Confirm both named routes, both schemas, and the exact legacy response. The prepared Laravel 12 and 13 applications each kept the legacy behavior unchanged and passed the new feature's two tests with 13 assertions. Commit only after your application proves both.

Stop and roll back safely

Stop on an unsupported platform or package identity, failing baseline, unsafe installer refusal, dry-run write, duplicate registration, Service/Domain/class/route/table collision, legacy drift, failed new test, destructive migration concern, outside-root write, or cleanup uncertainty.

Pulsar provides no uninstall workflow. Before committing, restore application files and Composer lock state to Checkpoint 0, reinstall that lock, and restore or reverse data only through the reviewed plan. After commit, use the team's normal revert and redeploy procedure for the one increment. Never broadly delete app/Pulsar, edit vendor, or guess that migrate:rollback --step=1 affects only this slice. Source control alone does not reverse production data or external side effects.

Account for application-specific behavior

Authentication, authorization, tenancy, queues, events, long-lived workers, package discovery, and third-party writes need their own parity and rollback evidence. Reused tables need an explicit compatibility design. Clear and rewarm only application-owned route, config, Event, or autoload caches with the team's normal commands. Custom bootstrap integration must be reviewed. Moving an established URL or Model is a later parity-tested migration, not an adoption prerequisite.

Review the increment

  • [ ] Supported PHP/Laravel/Composer and locked Pulsar v0.4.1 identity are confirmed.
  • [ ] The team agreed on the Service audience, Domain capability, and strict app/Pulsar boundary.
  • [ ] Existing targeted tests pass and the legacy route/response/schema/provider baseline is recorded.
  • [ ] A clean VCS commit and reviewed data reversal/backup procedure exist.
  • [ ] Intended Service, Module, Domain, class, route, table, migration, and provider names do not collide.
  • [ ] Installer dry-run exits 0, describes only expected seams, and writes nothing.
  • [ ] Installer apply is reviewed; rerun is idempotent; provider registrations occur exactly once.
  • [ ] The new feature passes its public-boundary tests on the application's supported environment.
  • [ ] The unchanged legacy checks still pass after install, Service registration, migration, and feature.
  • [ ] Cached application state has been handled deliberately, with no global Composer/Pulsar dependency.
  • [ ] Rollback covers source, lock file, database, and external side effects without an invented uninstall.
  • [ ] Every term on the page is defined or linked before its first use.