Background Jobs
Solid Queue, the add-job skill, and scheduling recurring work.
Anything that shouldn't hold up a request, sending a batch of emails, processing a webhook,
running cleanup, or a periodic task, runs as a background job. One Shot runs jobs on Solid
Queue, which is already configured and needs no Redis: in production it runs in-process inside
Puma, and in development and test it runs jobs inline or async automatically. perform_later just
works from a fresh clone.
The fastest way to add one is the add-job skill in Claude Code.
Creating a job
bin/rails g job SendInvoiceReminder
This generates app/jobs/send_invoice_reminder_job.rb. Keep perform small and idempotent: Solid
Queue may retry a job, so running it twice for the same input should be safe. Operate through
account-scoped associations inside the job, the same rule as everywhere else in the app; never
reach for a global scope like Invoice.find(id) when account.invoices.find(id) is available.
Enqueuing work
SendInvoiceReminderJob.perform_later(invoice.id)
Pass ids, not objects: by the time the job actually runs, the record you passed might have changed or been deleted, and an id forces the job to re-fetch current state rather than operate on a stale snapshot serialized at enqueue time. For work that should run later rather than now:
SendInvoiceReminderJob.set(wait: 1.hour).perform_later(invoice.id)
Recurring jobs
For work that should run on a schedule rather than in response to an event, add an entry to
config/recurring.yml, using cron-style scheduling. Solid Queue reads this file and schedules the
job itself; you don't need an external cron or a scheduler service.
Testing
Write spec/jobs/<name>_job_spec.rb, asserting the job's actual behavior with it performed inline
(perform_enqueued_jobs or the equivalent for your test setup). Wherever the job is triggered from
elsewhere in the app (a controller action, another job), assert on that trigger with
have_enqueued_job; the test adapter for this is already configured, so no additional setup is
needed.
Verify
bin/check should be green, including the new job spec.
Next
If the job needs to send an email, see Sending Email.