<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Postmortems - Medium]]></title>
        <description><![CDATA[In pursuit of transparency, we will publish a public postmortem for any serious outage on core Medium services. - Medium]]></description>
        <link>https://medium.com/postmortems?source=rss----ec92d26896cc---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Postmortems - Medium</title>
            <link>https://medium.com/postmortems?source=rss----ec92d26896cc---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 00:18:00 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/postmortems" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Monday 4 January 2021]]></title>
            <link>https://medium.com/postmortems/monday-4-january-2021-d0df736d7d1d?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/d0df736d7d1d</guid>
            <dc:creator><![CDATA[Brian Zotter]]></dc:creator>
            <pubDate>Wed, 27 Jan 2021 20:02:55 GMT</pubDate>
            <atom:updated>2021-01-27T20:02:55.408Z</atom:updated>
            <content:encoded><![CDATA[<h4>Post view stats issue</h4><p><strong>Summary</strong></p><p>From November 20th, 2020 to January 4th, 2021, some Medium authors saw intermittent spikes in post view stats.</p><p><strong>Impact</strong></p><p>Approximately 700 authors were experiencing large single-day spikes of story views (in most cases only in one post) of up to 1000 additional views in their stats details page. This did not impact the Member Reading time. As such, no Partner Program earnings revenue was lost or impacted. This also did not affect average read time.</p><p><strong>Timeline</strong></p><ul><li>January 3, 5:04 pm: We received a tweet at Medium Support describing the issue</li><li>January 4, 7:09 am: One of our employees sees the tweet then follows up by creating a ticket and exploring the issue</li><li>January 4, 8:56 am: We discover that a bad actor started emitting thousands of post viewed events to our server</li><li>January 6, 4:55 pm: More reports of the issue come in and this issue is marked as urgent</li><li>January 7, 2:42 pm: A new service was deployed to prevent this issue from happening again</li></ul><p><strong>Root cause</strong></p><p>A malicious external script was sending thousands of fake view events inflating views on stats pages.</p><p><strong>Action taken</strong></p><p>The IP of the script was blocked and we added additional security to detect and block these spam events. We will also be doing a data backfill to eliminate the fraudulent events.</p><p><em>The Medium Engineering team have committed to publishing a technical postmortem for serious outages to Medium core services, in order to build trust and hold us accountable to our users. </em><a href="https://medium.com/postmortems/public-accountability-5935ed4d5e5a"><em>More background on this program</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0df736d7d1d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/monday-4-january-2021-d0df736d7d1d">Monday 4 January 2021</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Wednesday 26 January 2018]]></title>
            <link>https://medium.com/postmortems/wednesday-26-january-2018-3d1e505a9abb?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/3d1e505a9abb</guid>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Mon, 29 Jan 2018 19:32:24 GMT</pubDate>
            <atom:updated>2018-01-31T00:48:06.686Z</atom:updated>
            <content:encoded><![CDATA[<h3>Summary</h3><p>On January 26th, 2018, Medium had a rolling outage from 4:51PM until 5:32PM.</p><h3>Impact</h3><p>A majority of requests to medium.com failed (including visits from a web browser, interactions from our native apps, and API requests).</p><h3>Timeline</h3><ul><li>4:51PM: Server errors began</li><li>5:31PM: A bad cache instance was identified and restarted</li><li>5:32PM: The last sustained server errors ended</li></ul><h3>Root cause</h3><p>At Medium, we run experiments that affect the behavior of the site, the apps, emails, and many other things — all with the goal of refining the Medium experience to make it better for our users. When a server processes a request or handles an event, it checks the status of all running experiments to ensure the correct response is delivered.</p><p>This outage was caused by the failure of a cache that stored metadata for currently running experiments. The resulting surge of requests that failed over to our database were beyond provisioned capacity and requests began to fail.</p><h3>Action taken</h3><p>We have taken steps to ensure that the cache is more resilient against the failures of instances serving hot cache keys.</p><p><em>The Medium Engineering team have committed to publishing a technical postmortem for serious outages to Medium core services, in order to build trust and hold us accountable to our users. </em><a href="https://medium.com/postmortems/public-accountability-5935ed4d5e5a"><em>More background on this program</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3d1e505a9abb" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/wednesday-26-january-2018-3d1e505a9abb">Wednesday 26 January 2018</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Tuesday 19 September 2017]]></title>
            <link>https://medium.com/postmortems/tuesday-19-september-2017-825c0849f275?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/825c0849f275</guid>
            <category><![CDATA[postmortem]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[medium-engineering]]></category>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Fri, 06 Oct 2017 01:31:00 GMT</pubDate>
            <atom:updated>2017-10-06T01:30:59.869Z</atom:updated>
            <content:encoded><![CDATA[<h4>Crash on app launch for users running iOS 11</h4><p>On September 19, 2017, version 3.3 of the Medium iOS app was released to the App Store. Apple released the official version of iOS 11 earlier that same day. Through a combination of factors, the app started crashing on launch for users running iOS 11.</p><h4>Timeline</h4><ul><li><strong>September 19, 3:22pm: </strong>Version 3.3 was released to the App Store.</li><li><strong>4:16pm:</strong> iOS engineers received an alert from Crashlytics about a crash affecting a large percentage of users on iOS 11 only.</li><li><strong>6:03pm:</strong> A fix for the crash was submitted in version 3.4 of the app with an expedited review request.</li><li><strong>September 20, 11:00pm:</strong> Version 3.4 of the app was approved and released.</li></ul><h4>Root cause</h4><p><a href="https://medium.com/p/2bfaaea75bfe">The crash was caused by a runtime type mismatch</a> between what type an object was declared to be and what type it was at runtime. This type mismatch was introduced a while ago, but didn’t start causing crashes until iOS 11.</p><p><em>The Medium Engineering team have committed to publishing a technical postmortem for serious outages to Medium core services, in order to build trust and hold us accountable to our users. </em><a href="https://medium.com/postmortems/public-accountability-5935ed4d5e5a"><em>More background on this program</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=825c0849f275" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/tuesday-19-september-2017-825c0849f275">Tuesday 19 September 2017</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Tuesday July 11th, 2017]]></title>
            <link>https://medium.com/postmortems/draft-for-the-public-post-mortem-for-outage-of-july-11th-2017-8190e503df7d?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/8190e503df7d</guid>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Wed, 26 Jul 2017 20:09:14 GMT</pubDate>
            <atom:updated>2017-07-26T20:30:43.255Z</atom:updated>
            <content:encoded><![CDATA[<h3>Summary</h3><p>On July 11th, 2017, Medium.com was not serving requests from 4:10 pm to 4:14 pm due to a deployment issue caused by a miscommunication.</p><h3>Impact</h3><p>No one could access <a href="https://medium.com/">https://medium.com</a> for 4mn.</p><h3>Root cause</h3><p>At Medium, all services are deployed following a <a href="https://en.wikipedia.org/wiki/Continuous_delivery">continuous integration and continuous deployment</a> model. What this means is that deployments of our services happen automatically at a high frequency (this service, in particular, gets deployed dozens of times a day). To make this process safe, our deployment pipeline runs a health check on a <a href="https://martinfowler.com/bliki/CanaryRelease.html">canary</a> to make sure that there is no obvious regression.</p><p>If the health check step passes, all production traffic is redirected to a fleet of servers running the new build.</p><p>If anything bad is discovered, the deployment pipeline stops and notifies the on-call team. The team then investigates the possible regression and decides between retrying the health check step or abandoning a build.</p><p>In this case, the health check step did not pass, and two different protocols were implemented simultaneously, causing an outage.</p><h3>Action Taken</h3><p>We took the necessary actions to prevent such issues from happening again by adding a lock to prevent an abandoned build from being retested and adding extra steps prior to the promotion of a build to make sure enough hosts are running the service before switching traffic to the new fleet.</p><h3>Timeline</h3><ul><li><strong>4:10 pm PDT</strong><br>Health check of our deployment pipeline mistakenly allows a terminated build to be promoted taking down <a href="https://medium.com/">https://medium.com</a></li><li><strong>4:14 pm PDT</strong><br>Oncall engineer rolls back the bad fleet and returns Medium to service</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8190e503df7d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/draft-for-the-public-post-mortem-for-outage-of-july-11th-2017-8190e503df7d">Tuesday July 11th, 2017</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Thursday 27 April, 2017]]></title>
            <link>https://medium.com/postmortems/thursday-27-april-2017-d156c3de9365?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/d156c3de9365</guid>
            <category><![CDATA[postmortem]]></category>
            <category><![CDATA[oop]]></category>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Thu, 04 May 2017 21:43:03 GMT</pubDate>
            <atom:updated>2017-05-04T21:43:02.999Z</atom:updated>
            <content:encoded><![CDATA[<p>On April 27th at 7:20 AM PDT, a group of hackers made changes to a few publications that are hosted on Medium.com by gaining access to the Twitter account of one of our editorial administrators. We quickly stemmed all unauthorized access to these publications, halted the hack and worked with the publications to revert their sites to their previous state. We are taking active security measures to restrict unauthorized access and prevent this from happening in the future.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d156c3de9365" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/thursday-27-april-2017-d156c3de9365">Thursday 27 April, 2017</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Wednesday 18 January 2017]]></title>
            <link>https://medium.com/postmortems/wednesday-18-january-2017-87877652859b?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/87877652859b</guid>
            <category><![CDATA[postmortem]]></category>
            <category><![CDATA[medium]]></category>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Tue, 24 Jan 2017 18:17:38 GMT</pubDate>
            <atom:updated>2017-01-24T19:18:20.078Z</atom:updated>
            <content:encoded><![CDATA[<h4>Distributed Denial of Service (DDoS) Attack on custom domains.</h4><p>On Wednesday morning at 6:45am PST, custom domains on Medium were subject to a 350x increase in network traffic due to a Distributed Denial of Service (DDoS) attack. Direct traffic to custom domains was affected, while direct traffic to medium.com remained unaffected.</p><p>Our on-call team was alerted within minutes and began working to resolve the issue. By 8:20am load times began improving and at 12:45pm custom domain performance was restored to 95%. Traffic reverted to normal at 5:30am Thursday morning and custom domain performance was back at 100%.</p><h4>Timeline</h4><ul><li><strong>6:45am PST<br></strong>On-call team registers 350x increase in network traffic. Within minutes the team increases the size and number of reverse proxies to manage the flood of traffic.</li><li><strong>8:20am PST<br></strong>Load times begin improving to many custom domains, but access remains intermittent.</li><li><strong>12:45pm PST<br></strong>Custom domains restored to 95% normal performance.</li><li><strong>5:30am PST (Thursday)<br></strong>DDoS attack ends. Custom domains restored to 100% normal performance.</li></ul><h4>Explanation of root cause</h4><p>The source addresses of the attack appear to have been spoofed, making it difficult to identify its origin.</p><h4>Explanation of resolution</h4><p>We mitigated the attack by increasing the number and size of reverse proxies to enable us to handle the flood of traffic to our servers.</p><h4>Preventative measures</h4><ul><li>We’re looking into a host of measures to prevent this type of attack from reaching custom domains’ reverse proxies in the future.</li></ul><p><em>The Medium Engineering team have committed to publishing a technical postmortem for serious outages to Medium core services, in order to build trust and hold us accountable to our users. </em><a href="https://medium.com/postmortems/public-accountability-5935ed4d5e5a"><em>More background on this program</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=87877652859b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/wednesday-18-january-2017-87877652859b">Wednesday 18 January 2017</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Monday 31 October 2016]]></title>
            <link>https://medium.com/postmortems/monday-31-october-2016-6ce8d12ebce0?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/6ce8d12ebce0</guid>
            <category><![CDATA[trick-or-treat]]></category>
            <category><![CDATA[postmortem]]></category>
            <category><![CDATA[outage]]></category>
            <category><![CDATA[oop]]></category>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Thu, 03 Nov 2016 15:21:23 GMT</pubDate>
            <atom:updated>2016-11-03T15:23:00.669Z</atom:updated>
            <content:encoded><![CDATA[<h4>Outage on post pages</h4><p>On Monday lunchtime a change was pushed to production that caused post pages to become unavailable. Due to an increase in load, a small percentage of traffic to other parts of the site were also intermittently unavailable, though at a much smaller scale. The CMS was unaffected.</p><p>The error triggered alerts and our on-call team reverted the bad build. The incident lasted 18 minutes, from 1:08pm to 1:26pm PST.</p><h4>Timeline</h4><ul><li><strong>1:03pm PST<br></strong>Health checks on the new build pass.</li><li><strong>1:06pm PST<br></strong>The deployment completes.</li><li><strong>1:08pm PST<br></strong>Alerts indicate abnormally high pressure on an internal service.</li><li><strong>1:16pm PST<br></strong>Alerts indicate server responses are too slow.</li><li><strong>1:19pm PST<br></strong>On-call triggers a rollback to the previous build deploy.</li><li><strong>1:26pm PST<br></strong>The rollback succeeds, all pages are again fully accessible.</li></ul><h4>Explanation of root cause</h4><p>On Monday a new feature, making a change to the rendered output of a post page, was rolled out to 100% of users, due in part to a desire to have a consistent experience for all users.</p><p>The data used to render Medium’s post pages comes from a number of backend services, supported by a number of different kinds of caches. During development of this new feature, a misconception about how cache abstractions work meant that the new feature queried <em>Hopper</em> (a backend data service) for every rendering of every post page.</p><p>As a result, once the deploy completed, Hopper saw a substantial spike in traffic, and was unable to handle the additional load. The machines backing Hopper rapidly approached 100% CPU, which caused requests to back up. Post pages in turn began to timeout, and the reverse proxies shed traffic.</p><p>The additional load on Hopper caused cascading slowdowns to other parts of Medium which relied upon it, causing intermittent — though less noticeable — failures throughout the rest of the site. Successful responses returned by Medium frontends were at 25% of what they were prior to the incident.</p><p>This class of issue is usually prevented through use of <a href="http://github.com/Medium/variants">variants</a> to roll new features out to progressively larger audiences. We start with Medium staff, then typically go to 10%, 25%, then 100% of Medium users. This is done both to assess the effectiveness of the feature, and to understand the impact of the feature on infrastructure. The Monday afternoon change bypassed this progressive rollout.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QTzd20Ior-PMYQrq0CIZTQ.png" /><figcaption>Medium FE Latency</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8-7wewG44sE9a_DpqB2ueg.png" /><figcaption>Hopper Num Go Routines</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hPaNdVbMIBrr43c_aShnIw.png" /><figcaption>Hopper Free Memory</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KGVtMZUXeABug6CZVGGzHQ.png" /><figcaption>Hopper CPU</figcaption></figure><h4>Explanation of resolution</h4><p>We resolved the short term issue by turning off the new feature. A permanent caching fix reduced the load on Hopper. The feature was then rolled out to 5% of users, then in small increments, allowing the team to understand the required capacity and add machines to the Hopper fleet as necessary.</p><h4>Preventative measures</h4><ul><li>Restatement of policy to avoid going from 0–100% of users in one step. We know this to be best practice, and we made a mistake by not doing so. In particular, launch plans should be designed to account for the fact that we can’t jump to 100% for anything that touches the post page.</li><li>Implement graceful degradation of non-critical features.</li></ul><p><em>The Medium Engineering team have committed to publishing a technical postmortem for serious outages to Medium core services, in order to build trust and hold us accountable to our users. </em><a href="https://medium.com/postmortems/public-accountability-5935ed4d5e5a"><em>More background on this program</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ce8d12ebce0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/monday-31-october-2016-6ce8d12ebce0">Monday 31 October 2016</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Wednesday 22 June 2016]]></title>
            <link>https://medium.com/postmortems/wednesday-22-june-2016-ece4017c99a5?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/ece4017c99a5</guid>
            <category><![CDATA[postmortem]]></category>
            <category><![CDATA[silence-is-not-golden]]></category>
            <category><![CDATA[outage]]></category>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Fri, 24 Jun 2016 23:49:47 GMT</pubDate>
            <atom:updated>2016-11-02T16:18:12.156Z</atom:updated>
            <content:encoded><![CDATA[<h4>Outage on publication home pages</h4><p>On Wednesday morning a change was pushed to production that caused some publication home pages to throw errors, including landing pages for hosted domains. Direct traffic to medium.com, CMS, and post pages was unaffected.</p><p>The error triggered alerts and our on-call team reverted the bad build. The incident lasted 21 minutes, from 10:04am to 10:25am PST.</p><h4>Timeline</h4><ul><li><strong>9:42am PST<br></strong>Health checks pass, despite errors on publication home pages.</li><li><strong>10:04am PST<br></strong>The deployment completes.</li><li><strong>10:09am PST<br></strong>Alerts indicate several major publication pages are offline.</li><li><strong>10:10am PST<br></strong>On-call triggers a roll-back to the previous build deploy.</li><li><strong>10:25am PST<br></strong>The rollback succeeds, publication home pages accessible.</li></ul><h4>Explanation of root cause</h4><p>Medium’s publication home pages are divided into “sections” which display stories from a variety of sources (e.g. the latest stories in the publication, featured stories, or stories from a tag). On Medium, stories can be tagged with topics that help readers discover related stories. Publications can use these tags to divide up their homepage on a per-topic basis.</p><p>Medium assumes that every tag uses title case by default. For certain popular tags that should not use title case, we manually override the name of the tag with the correct casing (for example, we use “MLB” instead of “Mlb”). Unfortunately, we weren’t using the overridden cases when rendering sections on publication home pages. In the process of fixing this issue, a bug was introduced where it was assumed that tag object would always exist for the corresponding slug:</p><pre>section.postListMetadata.tagName = tagsBySlug[tagSlug].name</pre><p>When the corresponding tag object does not exist, tagsBySlug[tagSlug] evaluates to undefined. We then attempt to access the name property of an undefined object, which throws an error.</p><p>Errors like this are ordinarily caught by unit tests, or during the “health check” phase of Medium’s deployment process. During this final phase, we test a single machine with production traffic before deploying the build to the rest of the fleet. We track the errors on this machine and halt the build if we encounter any unexpected errors.</p><p>The Wednesday morning build succeeded due to a false negative with the health checks. This caused our deployment process to interpret the build as safe, and escalate it to production.</p><h4>Explanation of resolution</h4><p>We resolved the initial bug by checking whether the tag object exists before attempting to access its properties. We also verified that the case where the tag object didn’t exist was safe, and corrected that case in a later fix.</p><h4>Preventative measures</h4><ul><li>Upgraded health check process with more probes for publication home pages and hosted domains.</li><li>Hardened health check process to prevent false negatives during health checks for this class of bug.</li><li>Will add additional unit tests for affected areas.</li><li>Will add additional end-to-end tests for publication features.</li><li>Identified steps to speed up rollback following event such as this.</li></ul><p><em>The Medium Engineering team have committed to publishing a technical postmortem for serious outages to Medium core services, in order to build trust and hold us accountable to our users. </em><a href="https://medium.com/postmortems/public-accountability-5935ed4d5e5a"><em>More background on this program</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ece4017c99a5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/wednesday-22-june-2016-ece4017c99a5">Wednesday 22 June 2016</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Thursday 3 March 2016]]></title>
            <link>https://medium.com/postmortems/thursday-3-march-2016-707aea7d6090?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/707aea7d6090</guid>
            <category><![CDATA[jinxed-it]]></category>
            <category><![CDATA[outage]]></category>
            <category><![CDATA[postmortem]]></category>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Tue, 08 Mar 2016 04:20:33 GMT</pubDate>
            <atom:updated>2016-11-02T16:18:40.051Z</atom:updated>
            <content:encoded><![CDATA[<h4>Medium Outage</h4><p>On Thursday morning a change was made to how EC2 instances are provisioned. This change, combined with lack of termination protection on key long-lived instances and loose IAM policies, resulted in instances being removed in a key availability zone. This impacted core infrastructure required for Medium’s operation.</p><p>The outage lasted 31 minutes, from 11:25am to 11:56am PST. Error rates remained elevated until 12:35 PST.</p><h4>Timeline</h4><ul><li><strong>11:20am PST</strong><br>A change to how we provision EC2 instances was made and executed.</li><li><strong>11:26am PST</strong><br>Increase in average response times coupled with a drop in traffic to application servers.</li><li><strong>11:27am PST</strong><br>Elevated server errors. On-call engineers are paged and respond immediately.</li><li><strong>11:32am PST</strong><br>On-call engineers identify that several reverse proxies are down, begin re-provisioning.</li><li><strong>11:44am PST</strong><br>Instances for several other services are offline. Process begins to rebuild fleet.</li><li><strong>11:55am PST</strong><br>Core services operational. medium.com and hosted sites are accessible.</li><li><strong>12:09pm PST</strong><br>Source of terminations identified as within our network. Production access tightened for remainder of incident.</li><li><strong>12:35pm PST</strong><br>All services operational and stable. Offline tasks are backed up, but not affecting user experience.</li><li><strong>12:56pm PST</strong><br>Root cause identified. Restrictions on production access lifted.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8u5xivC_vy8EtfKk9CyRtw.png" /><figcaption>Application server requests</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c2TLU2VU4AshIJ1kF_epCg.png" /><figcaption>Internal server errors</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VmbXtVNLMFyaqYyJMR20tQ.png" /><figcaption>Average latency</figcaption></figure><h4>Explanation of root cause</h4><p>Medium uses <a href="https://www.ansible.com/">Ansible</a> for configuration management and orchestration. The <a href="http://docs.ansible.com/ansible/ec2_module.html">EC2 module</a> has a feature which can enforce a specific number of instances based on the uniqueness of EC2 tags. This can be done with either tag/value pairs or based on the presence of a tag.</p><p>For example, the following guarantees a single instance with a given “Name” tag:</p><pre>count_tag:<br>  Name: &quot;{{ fullname }}&quot;<br>exact_count: 1</pre><p>For a particular internal service, we don’t want more than one instance, regardless of zone constraints. At the time, it wasn’t clear to us that the Ansible EC2 module has <a href="https://github.com/ansible/ansible-modules-core/blob/0bbb7ba38da07d2a9e562834264a2ee2fc9ceaf4/cloud/amazon/ec2.py#L782">specific checks that apply to a given zone</a>. And the zone was being set automatically elsewhere.</p><p>This leads us to the root cause of Thursday’s issue.</p><p>While debugging this particular problem the configuration was set to:</p><pre>count_tag: Name<br>exact_count: 1</pre><p>This means only allow one instance that has a <em>Name</em> tag, regardless of value.</p><p>Unfortunately this wasn’t executed in dry-run mode (-C) and ended up removing all but one instance in an availability zone.</p><p>We distribute most services across all availability zones, which meant we lost about 25% of our fleet.</p><h4>Explanation of resolution</h4><p>The immediate resolution was to re-provision the instances we lost.</p><h4>Preventative measures</h4><ul><li>Turning on termination protection for all our key long-lived instances, and making it the default behavior for new instances, will reduce impact of a similar incident in the future.</li><li>Making the dry-run (-C) flag on by default will give more insight into what will change and help avoid accidental changes while debugging configurations.</li><li>Creating an isolated testing environment for config changes will protect production services from bad config changes.</li><li>Tightening up IAM role policies will help ensure that destructive actions (e.g. ec2:StopInstances) are restricted to automation systems that require them.</li><li>Re-running disaster planning for loss of an availability zone will identify actions that will reduce the impact of such an event on core services.</li></ul><p><em>The Medium Engineering team have committed to publishing a technical postmortem for serious outages to Medium core services, in order to build trust and hold us accountable to our users. </em><a href="https://medium.com/postmortems/public-accountability-5935ed4d5e5a"><em>More background on this program</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=707aea7d6090" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/thursday-3-march-2016-707aea7d6090">Thursday 3 March 2016</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sunday 21 February 2016]]></title>
            <link>https://medium.com/postmortems/sunday-21-february-2016-2caf275e870?source=rss----ec92d26896cc---4</link>
            <guid isPermaLink="false">https://medium.com/p/2caf275e870</guid>
            <category><![CDATA[postmortem]]></category>
            <category><![CDATA[outage]]></category>
            <category><![CDATA[uh-oh-spaghettio]]></category>
            <dc:creator><![CDATA[Medium Engineering]]></dc:creator>
            <pubDate>Fri, 26 Feb 2016 01:57:21 GMT</pubDate>
            <atom:updated>2016-11-02T16:18:59.420Z</atom:updated>
            <content:encoded><![CDATA[<h4>Partial Medium Outage</h4><p>A bug was introduced Thursday that subtly broke caching for a subset of our database requests. This, combined with a lack of caching on some requests from logged out users, aggressive retry logic, and an increase in traffic from Talia Jane’s <a href="https://medium.com/@taliajane/an-open-letter-to-my-ceo-fb73df021e7a#.7mu8vw1lq">open letter</a> increased pressure on our web tier Sunday morning.</p><p>For 30 minutes, between 8:55am to 9:25am PST, Medium’s primary web servers returned 504s to 20% of requests. On-call engineers were paged and were online within five minutes. It took ten minutes to identify the root cause and another fifteen to fully resolve it.</p><h4>Timeline</h4><ul><li><strong>02/17 11:00am PST</strong><br>A change in how tags are cached is deployed to production.</li><li><strong>02/21 8:55am PST</strong><br>The tags table starts throttling and on-call engineers are paged.</li><li><strong>02/21 9:00am PST</strong><br>On-call engineers respond online.</li><li><strong>02/21 9:10am PST</strong><br>The problem is determined and our on-call engineers begin increasing the read capacity on the tags table.</li><li><strong>02/21 9:15am PST</strong><br>The first increase in read capacity is fully pushed to production. At this point, the error rate is reduced but there are still errors happening in production.</li><li><strong>02/21 9:20am PST</strong><br>On-call engineers bump read capacity on the table for the second time.</li><li><strong>02/21 9:25 PST</strong><br>The second increase in read capacity is fully pushed to production and the site is recovered.</li></ul><h4>Explanation of root cause</h4><p>Medium uses Amazon’s <a href="https://www.datadoghq.com/blog/how-medium-monitors-dynamodb-performance/">DynamoDB</a> database for serving much of the site’s content. We also have a Redis cache in front of Dynamo to help smooth out our traffic load and prevent spikes that would otherwise result in DynamoDB throttling our request load.</p><p>On Thursday, a change was made that was intended to make the fetching of cached post tags more efficient. An unintended side effect of this change was that we stopped caching an empty list for posts with no tags. With this change out in production, requesting the list of tags on a post without any tags started hitting DynamoDB 100% of the time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*QJlpnrnFSmR2RwT_tjiWBw.png" /><figcaption>The number of DynamoDB requests for post tags.</figcaption></figure><p>This issue wasn’t surfaced until the traffic spike on Sunday morning when we were paged for user facing errors and throttled DynamoDB requests.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/505/1*0U1WreMVBJgRpxH9XSDETw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/505/1*HAIpqAMkUC1p_HAecPc1QQ.png" /><figcaption>Percent of 200s &amp; 504s served [left] and count of throttled DynamoDB requests [right] on Sunday Morning.</figcaption></figure><p>Under the hood, the <a href="https://aws.amazon.com/sdk-for-node-js/">Node AWS SDK</a> automatically retries requests to DynamoDB — including throttled requests — up to 10 times. This led to an increase in requests being processed concurrently on the Medium web servers, and subsequently an increase in latency. Our proxy servers compensated by shedding load and returning 504s. From 8:55am to 9:25am, approximately 20% of the requests to medium.com and other domains hosted on our platform returned 504s.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/967/1*2trSIOOMsyUVsLtcHa5zTw.png" /><figcaption>Increase in average and 95th percentile web server reported DynamoDB query latency.</figcaption></figure><h4>Explanation of resolution</h4><p>Because the Dynamo table did not have the full protection of our cache, it became more vulnerable to increases in traffic. Temporarily bumping the read capacity Sunday morning helped us weather the spike, but was not a long term resolution.</p><h4>Preventative measures taken</h4><ul><li>Tuning the DynamoDB retry logic will decrease the perceived latency of throttled Dynamo queries. With fewer concurrent requests running on the system at once, the load caused by throttling shouldn’t spill over to other requests on the system like it did Sunday morning.</li><li>Increasing test coverage will help detect the class of bug where caching was bypassed.</li><li>Adding alerts that detect when access patterns to tables change will allow us to identify issues before users are affected.</li><li>Reevaluate <a href="https://aws.amazon.com/blogs/aws/auto-scale-dynamodb-with-dynamic-dynamodb/">Dynamic Dynamo</a> as a mechanism for adjusting provisioning levels more quickly than humans can respond.</li></ul><p><em>The Medium Engineering team have committed to publishing a technical postmortem for serious outages to Medium core services, in order to build trust and hold us accountable to our users. </em><a href="https://medium.com/postmortems/public-accountability-5935ed4d5e5a"><em>More background on this program</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2caf275e870" width="1" height="1" alt=""><hr><p><a href="https://medium.com/postmortems/sunday-21-february-2016-2caf275e870">Sunday 21 February 2016</a> was originally published in <a href="https://medium.com/postmortems">Postmortems</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>