Overview
Every hosting service moves through a predictable lifecycle managed by Commerce jobs and scheduled commands. No manual steps are required under normal operation — provisioning, suspension, and termination all happen automatically.
Lifecycle Diagram
Order Paid
│
▼
CreateHostingAccountJob ──▶ status: active
│
┌───────────┴───────────┐
│ │
Invoice Overdue Invoice Paid (on time)
│ │
▼ (no action)
SuspendHostingAccountJob
│
status: suspended
│
┌─────────┴──────────┐
│ │
Payment Received Still No Payment
│ (past termination
│ grace period)
▼ ▼
UnsuspendHostingAccountJob TerminateHostingAccountJob
│ │
status: active status: terminated
Stage 1 — Account Creation
Trigger: InvoiceService::markPaid() is called when a hosting invoice is paid.
What happens:
CreateHostingAccountJobis dispatched to the queue.- The job calls the server's provisioning module
createAccount(). - On success: the service record is updated with
username,panel_account_id, andstatus = active. - The action is written to
provisioning_log.
If the job fails after 3 retries, the service stays in
pendingand an admin alert is triggered.
Stage 2 — Suspension (Non-Payment)
Trigger: commerce:check-overdue-services (runs daily at 01:00).
The command finds all active services whose linked invoice is overdue beyond the configured grace period.
What happens:
SuspendHostingAccountJobis dispatched per affected service.- The job calls
suspendAccount()on the module. - On success:
status = suspended. - Client receives a suspension notice email.
Stage 3 — Unsuspension (Payment Received)
Trigger: Overdue invoice is paid — InvoiceService::markPaid().
What happens:
UnsuspendHostingAccountJobis dispatched.- The job calls
unsuspendAccount()on the module. - On success:
status = active. - Client receives an unsuspension confirmation email.
Stage 4 — Termination (Extended Non-Payment)
Trigger: commerce:check-termination-services (runs daily at 02:00).
The command finds all suspended services past the termination grace period.
What happens:
TerminateHostingAccountJobis dispatched.- The job calls
terminateAccount()on the module — the account is deleted from the panel. - On success:
status = terminated. - Client receives a termination notice email.
Termination is irreversible. All data on the panel is deleted. Ensure grace periods are configured appropriately in Commerce settings.
Job Reliability
All provisioning jobs share the same retry configuration:
| Setting | Value |
|---|---|
| Max attempts | 3 |
| Retry backoff | 60 seconds |
| Failure behavior | Logged to provisioning_log, admin alerted |
Scheduled Commands
| Command | Schedule | Purpose |
|---|---|---|
commerce:check-overdue-services |
Daily 01:00 | Dispatch suspend jobs for overdue services |
commerce:check-termination-services |
Daily 02:00 | Dispatch terminate jobs for long-overdue services |
Both commands require the Laravel scheduler to be running. Verify with:
php artisan schedule:list
Manual Overrides
An admin can manually trigger any lifecycle action from Admin → Services → [service] → Actions. This dispatches a new job immediately, bypassing the scheduler. Useful for:
- Force-creating an account stuck in
pending. - Manually suspending a service outside the normal invoice cycle.
- Recovering after a failed automatic job.