<story><title>Deploying a Django App with No Downtime</title><url>https://medium.com/@healthchecks/deploying-a-django-app-with-no-downtime-f4e02738ab06</url></story><parent_chain><item><author>Beltiras</author><text>I was responsible for a 10^6 views&amp;#x2F;day (due to most traffic being daytime, comes out to 10-20 req&amp;#x2F;sec) website running on Django.  I went through hell arriving at this solution because the system was in disarray when I took over and deployed on an expensive cloud solution (so resources were limited).  Finally I just put my foot down and demanded we buy servers instead, we would have more bare metal by a factor of 4 than we needed and we would pay only a fraction of what we did for the previous &amp;quot;solution&amp;quot;.  I could provision all the VMs I wanted, provided I didn&amp;#x27;t break the host.&lt;p&gt;I arrived at this procedure: Spin up a dyno, worker, caches and warm everything up.  Run smoketests to validate everything from the app-server onwards is lit and firing on all cylinders.  Redirect nginx traffic to the new setup.  If everything turns to shit in a second, reverse traffic change and re-evaluate.  If everything works and nothing is broken after an hour, take the old dynos&amp;#x2F;workers&amp;#x2F;caches offline.&lt;p&gt;The trick was if there were migrations that broke the older version that you did it in 2 or more steps to isolate the changed model interactions.&lt;p&gt;And nobody should be using gunicorn, it&amp;#x27;s way less performant than uWSGI (citing:&lt;a href=&quot;http:&amp;#x2F;&amp;#x2F;blog.kgriffs.com&amp;#x2F;2012&amp;#x2F;12&amp;#x2F;18&amp;#x2F;uwsgi-vs-gunicorn-vs-node-benchmarks.html&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;blog.kgriffs.com&amp;#x2F;2012&amp;#x2F;12&amp;#x2F;18&amp;#x2F;uwsgi-vs-gunicorn-vs-node...&lt;/a&gt;).</text></item></parent_chain><comment><author>parhamn</author><text>This has a name -- its called blue&amp;#x2F;green deploys. The idea is if you&amp;#x27;re running the &amp;#x27;blue&amp;#x27; version of the site, you run a new &amp;#x27;green&amp;#x27; version then then route traffic to it once everything is fine (usually at the LB level) and revert if necessary&lt;p&gt;The way you solve the migration problem (much harder than it sounds) is to do only non backwards breaking migrations between a blue green switch. So you end up doing your migrations in multiple deploys (e.g add a field, and start using the new field with no references to the old field in the code, then remove the old field in the next blue&amp;#x2F;green deploy). I&amp;#x27;ve generally found that it might not be worth the effort though depending on the context (especially if your initial healtcheck is before the migration).</text></comment>
<story><title>Deploying a Django App with No Downtime</title><url>https://medium.com/@healthchecks/deploying-a-django-app-with-no-downtime-f4e02738ab06</url></story><parent_chain><item><author>Beltiras</author><text>I was responsible for a 10^6 views&amp;#x2F;day (due to most traffic being daytime, comes out to 10-20 req&amp;#x2F;sec) website running on Django.  I went through hell arriving at this solution because the system was in disarray when I took over and deployed on an expensive cloud solution (so resources were limited).  Finally I just put my foot down and demanded we buy servers instead, we would have more bare metal by a factor of 4 than we needed and we would pay only a fraction of what we did for the previous &amp;quot;solution&amp;quot;.  I could provision all the VMs I wanted, provided I didn&amp;#x27;t break the host.&lt;p&gt;I arrived at this procedure: Spin up a dyno, worker, caches and warm everything up.  Run smoketests to validate everything from the app-server onwards is lit and firing on all cylinders.  Redirect nginx traffic to the new setup.  If everything turns to shit in a second, reverse traffic change and re-evaluate.  If everything works and nothing is broken after an hour, take the old dynos&amp;#x2F;workers&amp;#x2F;caches offline.&lt;p&gt;The trick was if there were migrations that broke the older version that you did it in 2 or more steps to isolate the changed model interactions.&lt;p&gt;And nobody should be using gunicorn, it&amp;#x27;s way less performant than uWSGI (citing:&lt;a href=&quot;http:&amp;#x2F;&amp;#x2F;blog.kgriffs.com&amp;#x2F;2012&amp;#x2F;12&amp;#x2F;18&amp;#x2F;uwsgi-vs-gunicorn-vs-node-benchmarks.html&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;blog.kgriffs.com&amp;#x2F;2012&amp;#x2F;12&amp;#x2F;18&amp;#x2F;uwsgi-vs-gunicorn-vs-node...&lt;/a&gt;).</text></item></parent_chain><comment><author>CoffeeDregs</author><text>&lt;p&gt;&lt;pre&gt;&lt;code&gt;    And nobody should be using gunicorn, it&amp;#x27;s way
    less performant than uWSGI
&lt;/code&gt;&lt;/pre&gt;
uWSGI may be different now, but 4 years ago I built a browser toolbar C&amp;amp;C API server that peaked at about 2k requests per second.  We used uWSGI to front our Django application with SoftLayer HTTP load balancers in front of uWSGI.  uWSGI was speaking HTTP and translating to WSGI, but did so only in one thread&amp;#x2F;process. So while 8-16 Django threads were tootling along, the single uWSGI HTTP-&amp;gt;WSGI thread was pegged.  We switched to gunicorn and had dramatically better performance.</text></comment>