How we moved month-end close from a 2-day spreadsheet marathon to a 4-hour, queue-driven job.
LaravelERPQueuesPostgreSQL
The problem
When we first shipped the ERP, month-end close meant a finance lead spent two full days reconciling spreadsheets against the live ledger. The system was correct — it was just synchronous, and every month-end report ran on the request thread.
What we changed
We pushed every long-running job onto a Redis-backed queue: payroll runs, depreciation, recurring journals, PDF report generation, and period-close itself. The web request became a lightweight "kick off a job and show a progress card" handler.
The data model bit
The real unlock wasn't the queues — it was period locking. Once a month is closed, no entry can mutate that period silently. That meant we could safely cache report aggregates and trust them.
Outcome
Close time dropped from two days to four hours, and the finance team stopped fearing the last day of the month.