В моем случае проект был написан «абы-как». Точнее, довольно грамотно, но без каких-либо мыслей о том, что пользователей станет много, и придется как-то масштабировать. Более-менее красивый код, куча таблиц, связанных друг-с-другом, то есть чуть ли не десятки JOIN'ов. Кэширование не использовалось вообще.
Все работало (и работает) на 3-х серверах: база PostgreSQL, nginx для статики, nginx с gunicorn для собственно приложения.
Первые два года этого хватало, но росло количество пользователей и фич, в итоге, приходится периодически садиться и переписывать куски кода: денормализовывать базу, чтобы избежать JOIN'ов и поисков в дополнительных справочных таблицах, пытаться воткнуть кэширование (самая большая головная боль — кэширование надо предусматривать в самом начале и очень-очень хорошо продумывать), и т.д. и т.п.
Просто описываю свой опыт. Мне кажется, мораль такая — не надо изначально все переусложнять. Надо думать о производительности, но не до фанатизма. Скорее всего, на первых порах хватит простого кода и одного-двух серверов. Вряд ли у вас сразу же получится вторая мордокнига по популярности. Напротив, те, кто думают, что их проект тут же захватит мир, чаще всего ошибаются.