Как гарантировать списание денег с баланса?
без разницы как Вы будете запускать процесс списания средств по крону или еще как-то, защита от повторного/параллельного списания должна быть реализована в самом алгоритме списания и не зависеть от вызывающих ее процессов. Т.е. на момент списания алгоритм сам должен проверять нужно ли снимать абонплату с клиента или нет. Как именно сделать эту защиту зависит от деталей реализации Вашей системы - но в общем случае вариант с историей вполне уместен, а проблемы параллельного списания вполне можно решить транзакциями/блокировками
а что если
так до бесконечности можно, нужно просто сесть и начать делать.
А нужно всего лишь нормально написать код, так чтобы два раза не могло списаться никак, всего лишь нужна проверка логов на списывалось уже или нет. Не говоря уже про другие факторы которые говорят о том что списание уже было(дата подписки же где-то должна изменяться на свежую и т.д.)
Если сервер упадёт то в любом случае надо либо руками разгребать что произошло и что надо подправить/запустить кроны или еще что-то, либо рассчитывать код на то что вчера допустим крон не отработал, и надо захватить все еще не продленных клиентов и попробовать их продлить. Т.е. по сути тупо как обычно продлить тем кому пришла пора продлять.
Например даже с сегодняшней даты если продлять, то ничего страшного не случится с ними. 
Прошедший день станет бесплатным, если вы конечно не хотите брать деньги даже за дни которые ваш сервер лежал.