BackgroundTasks run in the same process after the response is sent. If that process restarts (deploy, crash, Railway recycling the container, scaling down), queued tasks are simply gone. No retry, no trace. That fits "1 in 20, no log line".
For anything that must happen, use a real queue. Doesn't have to be Celery: arq or rq with Redis is ~20 lines. Or, simplest of all, a pending_emails table that a small cron picks up and marks sent.