Save and Resume Long Laravel Forms with Livewire 4
Save and Resume Long Laravel Forms with Livewire 4
“Save progress” is not one feature. A same-browser session draft, an authenticated account draft, and a guest resume link have different identity, privacy, and concurrency models. Choose the model before adding autosave to a Livewire component.
Pick the identity model
| Model | Cross-device | Guest-friendly | Revocable | Best fit |
|---|---|---|---|---|
| Session draft | No | Yes | Indirectly | Short same-browser continuation |
| Authenticated database draft | Yes | No | Yes | Portals and internal workflows |
| Guest database draft + bearer link | Yes | Yes | Yes, with a token record | Applications and long public forms |
Session storage is simplest, but expires with the session and can suffer concurrent-write behavior. An authenticated model gives strong ownership. A guest link supports cross-device continuation but must be treated like a password to the draft.
Store drafts separately from submissions
A useful draft record includes:
form_id
form_version_id
user_id (nullable)
resume_token_hash (nullable)
data (partial JSON)
current_step
locale
lock_version
last_saved_at
expires_at
completed_at
Do not create a final submission until full validation succeeds. Draft data can be incomplete by design and should not pollute completion metrics or downstream notifications.
Bind the draft to an immutable form revision. When that revision retires, explicitly allow completion, migrate the data, or require restart. Silent validation against a newer schema is the most dangerous option.
Autosave without pretending the draft is valid
Livewire 4 provides the mechanisms: debounced or blur updates, lifecycle hooks, wire:dirty, and loading states. The Livewire forms documentation shows the current primitives.
On autosave, validate structure and the fields being stored: allowed keys, scalar/array type, size bounds, and ownership of referenced records. Reserve full required/cross-field validation for final submission.
This distinction lets a visitor save halfway through an empty required step without allowing malformed or oversized data into the draft store.
Make guest links secret and revocable
Generate a cryptographically random token, show it only in the resume URL, and store only its hash. The lookup should require:
- a matching active token hash;
- an unexpired, incomplete draft;
- the expected form/tenant context;
- rate limiting;
- HTTPS and a trusted host.
Laravel temporary signed URLs prove that parameters were not modified and can expire. They are not automatically single-use or revocable. A database token record supplies revocation and rotation. Use Laravel signed URLs as one layer, not the entire access model.
Avoid PII in the URL and configure a referrer policy so the bearer token is not leaked to third-party resources.
Prevent two tabs from silently overwriting
Autosaves can race. Add an integer lock_version; update with where('lock_version', $expected) and increment it atomically. If zero rows update, show a conflict instead of applying last-write-wins invisibly.
For session-backed drafts, Laravel session blocking can serialize selected same-session routes, but it does not solve cross-device database conflicts. Review the session concurrency documentation.
Treat draft uploads as real private data
Livewire temporary upload references are not durable draft storage. Move retained files into a controlled private draft area, generate storage names, record ownership, and authorize every preview/download.
When the draft completes, atomically associate retained files with the submission. When it expires or is deleted, remove them. Our file upload security guide covers validation and retrieval controls.
Expire and clean up deliberately
Drafts contain personal data even when never submitted. Set an expiry based on the workflow, notify users if appropriate, and schedule bounded cleanup for draft rows, attachments, tokens, and safe audit metadata.
A cleanup job should be idempotent and observable. A legal or support hold needs an explicit owner and review date rather than an undeclared infinite expiry.
Final submission flow
When the visitor submits:
- authorize the user or bearer token;
- lock the draft and verify its revision;
- compile complete validation rules;
- validate the full stored-plus-current payload;
- create one submission and attach files in a transaction;
- mark the draft complete and invalidate its token;
- dispatch notifications/integrations after commit.
Use an idempotency key so a timeout or double-click cannot turn one completed draft into two submissions.
Tests that catch real failures
- an expired or revoked link cannot read a draft;
- only a token hash is stored;
- two-tab updates cause a visible version conflict;
- an autosave accepts incomplete data but rejects unknown keys and oversized collections;
- final submit enforces every rule;
- a draft remains bound to its original revision;
- abandoned files are deleted and completed files survive;
- replaying a completed link cannot resubmit;
- a cross-tenant draft identifier fails authorization.
Build the multi-step experience first—our Filament wizard guide covers that layer. Then add persistence as an identity and data-lifecycle feature, not just a debounced database update.