Think about this problem first.
What happens on the last day of the month, at the time the server is going to run the cron something happens and the server is down for 30 minutes. When should the cron run now?
So lets solve that problem first.
We'd probably run a command, which "checks to see if today is the last day of the month for this client and it's past 8PM, and if we haven't successfully run the code we need to run, then run it".
So we could create cron log object (or, end of month report or end of month cleanup)
client_id | month | status
So we can then query this table to see if we have ran the cron already.
Then if we just set the cron to run every 5 minutes all the time, check to see if it's ran for the client (db query) and if not and it's the last day of the month and it's past 8PM for that client then log and go.
Make sensish?
That way if server is down for a bit, or something happens it will still run.
You could fake 1,000 users and see what performance is like. But if you have 1,000 users and they are paying even $1 then this becomes a nice problem to solve :)
--
TLDR; Track if the cron has run for the client for the month or not. If not and past the time needed then run it. Run the cron every 5 minutes, even if only on the 28th to the 2nd server time to catch all...