<?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[Stories by Luke Demi on Medium]]></title>
        <description><![CDATA[Stories by Luke Demi on Medium]]></description>
        <link>https://medium.com/@lukedemi?source=rss-8dcf8e219b0b------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*Gq8EbrAZgiGcodM7P4Xt-Q.png</url>
            <title>Stories by Luke Demi on Medium</title>
            <link>https://medium.com/@lukedemi?source=rss-8dcf8e219b0b------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 23:46:00 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@lukedemi/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[The Annoying State of Lambda Observability]]></title>
            <link>https://medium.com/@lukedemi/the-annoying-state-of-lambda-observability-465470403846?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/465470403846</guid>
            <category><![CDATA[observability]]></category>
            <category><![CDATA[lambda]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[serverless]]></category>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Thu, 27 Jun 2019 04:13:05 GMT</pubDate>
            <atom:updated>2019-06-27T04:13:05.988Z</atom:updated>
            <content:encoded><![CDATA[<p>Unless you’re willing to buy entirely into AWS CloudWatch or X-Ray for all of your serverless observability needs, the process of integrating observability systems to AWS Lambda is a frustrating endeavor.</p><p>Gathering events from applications in the dark, legacy, “serverful” world was a straightforward task — simply embed an agent process onto each server in your infrastructure to batch up system metrics and application events (“telemetry”) before asynchronously delivering them to your metrics/logs/event provider of choice.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/573/0*lGrU2Zwh73Ygi_TU" /></figure><p>In an AWS Lambda world, custom agents and unsanctioned background tasks are a pattern of the past. Function execution stats are collected exclusively by AWS CloudWatch, spans are sent via UDP to an X-Ray agent embedded on every Lambda host, and logs are collected asynchronously by some background process and relayed to CloudWatch Logs. In their serverless ecosystem, AWS has replaced all of the traditional agents with their own.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sxAj9MaliMitivi2" /></figure><p>In many ways, these changes can be spun as a great convenience rather than as a vendor lock-in trap. After all, for those willing to buy in completely to the AWS observability ecosystem, no more configuration is required — simply emit traces to X-Ray or logs to CloudWatch, and make do with the AWS observability interface.</p><p>Yet many of us are already using non-AWS tooling or simply demand more than what CloudWatch or X-Ray can provide. What options exist to send events to observability tooling outside of the AWS walled garden?</p><p>In the current state of the world, the available strategies boil down to either:</p><ol><li>Send telemetry directly to external observability tools during Lambda execution.</li><li>Scrape or trigger off the telemetry sent to CloudWatch and X-Ray to populate external providers.</li></ol><p>Spoiler: neither option is ideal.</p><p><strong>Send</strong></p><p>Under the hood, Lambda functions are just containers that are unfrozen (or instantiated) when invoked by an event. Once a function has returned a response, it is frozen again where it waits for either another invocation or to be garbage collected and sent to Lambda heaven.</p><p>Since Lambda functions are frozen following their invocation, any telemetry must be sent <em>during</em> a function’s invocation. Otherwise, events batched up between invocations or sent in asynchronous background threads can be lost when functions are garbage collected between invocations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*7GJk_PuQ68WruY9k" /></figure><p>This leads to the big problem with the “Send” approach: any runtime telemetry must either be sent across the network as events occur or batched into a report sent at the conclusion of the function’s execution (but before returning success). The sad state of affairs is that when using the “Send” approach, users must be comfortable either losing some of their events, or pay a latency penalty to send telemetry on every single Lambda invocation.</p><p>Major latency penalty aside, the “Send” approach has many benefits:</p><ul><li>No additional infrastructure is required within AWS, since the telemetry is sent directly to the provider.</li><li>Telemetry is low latency. As soon as the Lambda function returns, we can feel secure that our events are being processed by our provider.</li><li>No additional cost is incurred to process events after the fact (as we’ll see with the “Scrape” approach below)</li></ul><p><strong>Scrape</strong></p><p>The most common approach to bypass the per-invocation performance penalty of the “Send” approach is to instead “Scrape” CloudWatch and X-Ray to gather metrics/logs/traces into your provider of choice.</p><p>A commonly utilized strategy is for functions to print events or metrics to standard output. These standard output events can then be wired up to trigger a separate Lambda function which can then forward events to external logging or metrics services. Frustratingly, AWS only allows a single Lambda function to attach to any single CloudWatch “Log Group”, so users must set up a fan-out Lambda function to a Kinesis Data Stream to send events or metrics to multiple providers.</p><p>Gathering trace or invocation stats for a given function is even less elegant — providers must actively scrape the AWS API every X minutes (which if set too frequently exasperates the hidden AWS API limit). Manually scraping traces leads to another vendor lock-in trap: how do you tie together the traces sent to X-Ray with the traces from calling services? Vendors have been forced to come up with clever techniques to tie these traces together.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/817/0*9j43cftE4-FFGb7E" /></figure><p>The “Scrape” method solves the exact opposite problems of “Send” — users are able to save latency Lambda invocations, but in turn are forced to build (potentially expensive) Rube Goldberg style machines to relay and scrape logs and traces from AWS’s products.</p><p><strong>An Ideal World</strong></p><p>Observability for Lambda is in a particularly annoying place — either buy in to AWS’s offerings (CloudWatch/X-Ray), take a performance hit, or build a Rube Goldberg machine.</p><p>Yet there could be a better way — rather than force users to build elaborate systems to “scrape” or IPC messages from inside Lambda functions, AWS could provide some type of UDP listening agent on each Lambda host — these agents could perform a similar function to the existing X-Ray agent, but rather than send events to AWS’s X-Ray service, forward them to a customer owned Kinesis Stream. Maybe even call them Lambda Event Streams.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*320G8Zc5VxGzH9Dc" /></figure><p>In this ideal new world, users could plug and play Lambda functions (custom or vendor provided) to consume whatever log/event/metric/trace telemetry that their Lambda functions are generating. No more latency penalty on event generation, and no more Rube Goldberg machines on the backend!</p><p>Since AWS isn’t going to fix this issue over night, we’re all left with this annoying trade off: use the AWS observability tooling wholesale, send metrics during execution time, or scrape into our own systems. Personally, I’m going to stick with the “send approach” — paying the additional latency is a small cost compared to the hassle of setting up a series of points of failure inside my own infrastructure. I’d love to use AWS’s tooling for everyone, and think AWS is getting a lot closer with products like CloudWatch Insights, but I think that AWS needs to take custom CloudWatch metrics just a little bit more seriously for me to abandon third party products entirely.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=465470403846" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Exploring serverless technology by benchmarking AWS Lambda]]></title>
            <link>https://medium.com/the-coinbase-blog/benchmarking-aws-lambda-ca3cfb3c25cd?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/ca3cfb3c25cd</guid>
            <category><![CDATA[lambda]]></category>
            <category><![CDATA[ruby]]></category>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Thu, 28 Mar 2019 16:38:22 GMT</pubDate>
            <atom:updated>2019-03-29T16:36:13.254Z</atom:updated>
            <content:encoded><![CDATA[<p>At Coinbase, we’re excited for the potential of serverless — if implemented correctly it can provide strong security guarantees and “infinite” scalability at a dramatically lower cost. As we’ve explored the potential for serverless, we’ve found ourselves curious about the real world performance of certain use cases. Some of the questions we’ve begun to ask include:</p><ul><li>How dramatic is the VPC cold start penalty really? This has a big impact on what database technology we choose (AWS DynamoDB and <a href="https://aws.amazon.com/about-aws/whats-new/2018/11/aurora-serverless-data-api-beta/">AWS Aurora Serverless</a> have “public” APIs). We’d heard that ENI Cold Start could be up to 10 seconds, is that really true? How frequently?</li><li>How does the size of the Lambda affect cold start times? If a smaller package can reduce cold start times, it may make sense to divide Lambdas into smaller packages. Otherwise, it might make more sense to leverage “monolith” Lambdas.</li><li>We’d read that <a href="https://theburningmonk.com/2017/06/aws-lambda-compare-coldstart-time-with-different-languages-memory-and-code-sizes/">Python can actually exhibit faster cold start times than Golang</a> in the context of Lambda execution. As a Ruby/Golang shop we’re curious to see how the performance of our runtimes stack up.</li></ul><h3>Terminology</h3><p>If you read the above bullet points without skipping a beat, feel free to skip on to the next section. Otherwise, the below vocabulary section should help provide a refresher to some of the terms used throughout the post.</p><ul><li><strong>AWS Lambda</strong> — Fully managed compute as a service. AWS Lambda stores and runs code (“functions”) on demand. Functions are run inside of sandboxed containers on host machines managed by AWS and created automatically to respond to changing demand.</li><li><strong>Warm Start</strong> — Between function executions, containers are “paused” on the host machine. A warm start is any execution of an AWS Lambda function where an idle container already exists on a host machine and is executed from this paused state.</li><li><strong>Cold Start</strong> — When a function is executed but an idle container does not exist, AWS Lambda will start a new container to execute your function. Since the host machine needs to load the function into memory (from presumably S3), cold start executions exhibit longer execution times than warm starts.</li><li><strong>ENI </strong>— Elastic Network Interfaces represent a virtual network card and are required for Lambdas to communicate to resources inside of an AWS VPC (Virtual Private Network) to access resources like internal load balancers, or databases like RDS or Elasticache.</li><li><strong>ENI Cold Start </strong>— In order to communicate inside a VPC, an ENI matching the security group of the Lambda must exist on the host machine when a function is initialized. If an ENI does not already exist on the host machine, it must be created before a function can be executed. ENIs can be reused between Lambdas that share the same security group, but cannot be shared across security groups even for the same VPC. AWS Plans to fix these issues <a href="https://twitter.com/jeremy_daly/status/1068272580556087296">sometime in 2019</a>.</li><li><strong>Box Plot</strong> — A method to visually represent numeric data by quartile. In this post outliers are shown as points outside of the box.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OeTJnD7Lv903ViId" /></figure><h3>The Setup</h3><p>We began poking around on the internet to find the answers to our questions and found several great papers and blog posts. However, there were some questions that we didn’t feel had been directly answered, or at least not in the context of the specific technologies we were using. Besides, even if we trust the results of the tests, why not verify? So we decided to take an attempt at discovering our own answers to these questions.</p><p>We wrote a small testing harness and a series of simple Lambdas to perform these tests. Really we only needed our framework to perform a series of cold and warm invocations of a given Lambda package. We are able to detect whether a Lambda is invoked cold or warm by setting a global variable “cold” to false on first execution so that while the first invocation will return “cold = true”, every subsequent invocation will return “cold = false”. We are able to force cold starts by simply re-uploading a function’s payload.</p><p>We used three different sources to measure invocation time: billing duration, observed duration, and AWS X-Ray trace statistics. Since billing duration does not include cold start time, and X-Ray trace statistics do not include ENI creation time, we use observed time for most of our tests.</p><h3>Database/VPC Performance</h3><p>Our first test was designed to test the performance of our most common databases from inside of Lambda. Since most of the databases we leverage live inside an AWS VPC, this test would also inherently test the performance of Lambdas created inside a VPC (this mainly being the additional time necessary to initialize an ENI on the host where our Lambda lived).</p><p>We tested six databases, Aurora Serverless, Aurora MySQL, DynamoDB, Elasticache Redis, Elasticache Memcached, and MongoDB (Atlas). All except for Aurora Serverless and DynamoDB required us to create the Lambda inside a VPC.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/793/1*iGfvbqLvKn2Iwj10FXHLqw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/789/1*UfZ5F0bCqwDDR5hiYqx1Cg.png" /></figure><p>The results from the cold start test surprised us. We had expected ENI creation to contribute more frequently to the cold start time of the Lambdas that were created inside a VPC. Instead, cold start times seemed to be consistent across the board other than significantly more outliers on VPC Lambdas.</p><p>It became clear from these results that not every VPC cold start requires ENI creation. Rather, AWS reuses existing ENIs during Lambda execution. So while technically Lambdas in a VPC were more liable to experience an ENI Cold Start, the number of cold starts experienced was dependent on the total number of existing ENIs in the invoking Lambda’s security group.</p><p>We wanted to understand more reliably the impact of an ENI Cold Start on Lambda invocation time. So we ran the test again and forced ENI creation by recreating VPC Lambdas in a temporary new security group before each invocation. These tests more clearly highlight the heavy penalty of an ENI Cold Start, requiring at minimum 7.5 seconds and frequently more than 20 seconds!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/953/1*q2ICgFGOJUvGTipYWQ6wbw.png" /><figcaption>Usain Bolt can run 100m faster than it takes to ENI Cold start a Lambda</figcaption></figure><p>These tests remind us to be careful when placing VPC Lambdas in hot or customer facing paths. Some potential strategies we are looking at to mitigate the impact of ENI Cold Starts are to let related Lambdas share security groups (and therefore ENIs) or placing all VPC Lambdas on a 5–10 minute timer to ensure ENIs are created ahead of execution.</p><h3>Package Sizes</h3><p>Our second test was designed to understand the cold start performance of package sizes across the AWS Lambda memory sizes. We’d read that the amount of compute provided to a given AWS Lambda function is based on the provisioned memory of the function.</p><p>This test was no different than the previous test, except this time we simply included large randomly generated files in the zip we uploaded to Lambda.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/792/1*LR3RioSqh31lw0vTkKD2RQ.png" /></figure><p>The results for this test were clear: big package sizes equal big cold start penalties. It follows that Lambda pulls down a function’s package to the invoking host on cold starts, but what’s less clear is why there’s such a massive penalty on larger sized packages. The simple math is that a 10s cold start for a 249MB package is a download speed of 200mbps, quite a bit below the 25gbps that an r5.metal or similar <em>could</em> provide. This indicates that AWS is throttling cold start bandwidth on a per-lambda basis. The lack of a performance boost on larger memory Lambdas seems to imply that this is not dependent on Lambda memory size.</p><h3>Runtime</h3><p>Our final test was designed to understand the cold and warm start performance of the various AWS Lambda runtimes. We chose to compare Ruby and Golang (along with Python as a control) since they’re the primary languages we leverage internally. This test executes a very simple scripts that simply returns the “cold” global variable and the root X-Ray trace ID.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/1*WWwnNRN7Uzr1Xw2ts3UA-A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/771/1*FR7f0BqK1mp1vcPrzw6E3Q.png" /></figure><p>The results of the test indicate that while Golang comes out on top for both cold and warm start performance, there is not a dramatic difference in execution time between the three languages. The results of this test allow us to feel comfortable allowing engineers to write Lambda functions in whichever language they feel most comfortable.</p><h3>Summary</h3><p>In summary some of our major takeaways include:</p><ul><li>Any ENI Cold Start in a hot/customer facing path will result in what we consider to be an unacceptable spike in latency. ENI Cold Starts can be mitigated by allowing shared Lambda functions to share security groups (at least until AWS <a href="https://twitter.com/jeremy_daly/status/1068272580556087296">solves these issues sometime in 2019</a>).</li><li>Lambda package size does matter significantly for cold start executions. Users should be careful to avoid hot paths with packages in the 100MB+ range.</li><li>Provisioned Lambda memory size matters less than anticipated — at the lower end of the scale (128MB) we were able to observe heightened response times, but the impact of size on lambdas larger than 512MB was negligible.</li><li>The difference between compiled and interpreted languages (Golang vs Ruby) turned out to be far less dramatic than we had anticipated. As a result we can feel comfortable allowing developers to write functions in whichever language they feel most comfortable.</li></ul><p>We’re excited to run these same tests in the future to see how AWS Lambda performance is changing over time!</p><p>If you’re interested in helping us <a href="https://www.coinbase.com/careers">build</a> a modern, scalable platform for the future of crypto markets, we’re hiring in <a href="https://www.coinbase.com/careers/positions/1525954">San Francisco</a>!</p><p><em>This website may contain links to third-party websites or other content for information purposes only (“Third-Party Sites”). The Third-Party Sites are not under the control of Coinbase, Inc., and its affiliates (“Coinbase”), and Coinbase is not responsible for the content of any Third-Party Site, including without limitation any link contained in a Third-Party Site, or any changes or updates to a Third-Party Site. Coinbase is not responsible for webcasting or any other form of transmission received from any Third-Party Site. Coinbase is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement, approval or recommendation by Coinbase of the site or any association with its operators.</em></p><p><em>Unless otherwise noted, all images provided herein are by Coinbase.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ca3cfb3c25cd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/the-coinbase-blog/benchmarking-aws-lambda-ca3cfb3c25cd">Exploring serverless technology by benchmarking AWS Lambda</a> was originally published in <a href="https://medium.com/the-coinbase-blog">The Coinbase Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Logs, metrics, and the evolution of observability at Coinbase]]></title>
            <link>https://medium.com/the-coinbase-blog/logs-metrics-and-the-evolution-of-observability-at-coinbase-13196b15edb7?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/13196b15edb7</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[elasticsearch]]></category>
            <category><![CDATA[metrics]]></category>
            <category><![CDATA[monitoring]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Mon, 11 Feb 2019 18:31:08 GMT</pubDate>
            <atom:updated>2019-02-12T17:53:22.092Z</atom:updated>
            <content:encoded><![CDATA[<p>Up until mid 2018, the only supported way to generate custom metrics for an application at Coinbase was to print to standard output. Each printed line would work its way through a series of pipelines where they could be analyzed, transformed, and parsed until finally landing on an index in our monolithic self-managed Elasticsearch cluster, where engineers could build visualizations and dashboards with Kibana.</p><p>This workflow represents the best of many worlds. Log entries are easy to generate, and because they can contain fields with unlimited cardinality at microsecond granularity, it’s possible to slice, dice, and aggregate these entries to diagnose the root cause of even the most complex issues.</p><p>In 2016, we reaffirmed our decision to self-manage Elasticsearch. At the time, managed solutions like Amazon Elasticsearch Service were still in their infancy (for example, IAM policy changes would require a full redeploy of the cluster) and we were reluctant to trust not yet mature third party vendor technology at the time with the potentially sensitive nature of our applications’ standard output data. We built elaborate automation to manage and blue-green deploy our Elasticsearch data, master and coordinating nodes with our existing deployment pipeline and comply with our self-enforced <a href="https://maori.geek.nz/keystone-metrics-in-devops-the-30-day-project-coinbase-b6c4e0109016">30 day project</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*57h8d3PwG4lf2aD2" /><figcaption>Visualizing our elaborate Elasticsearch deployment strategy.</figcaption></figure><p>Managing this newly automated Elasticsearch ourselves actually worked out fine for over a year. As an organization of thirty engineers serving up two moderately trafficked web applications, both our indexing (~100GB per day) and search volume (a few queries per minute) were relatively tame.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YLFhBWdxGOrg9dIX" /><figcaption>Backend API requests per minute over the course of 2017.</figcaption></figure><p>However during 2017, <a href="https://trends.google.com/trends/yis/2017/GLOBAL/#98691050-1c42-4eca-be44-417bc6853e61">interest in cryptocurrency skyrocketed</a>, catapulting our moderately trafficked web applications into the spotlight. This massive surge in traffic to our customer facing applications (60x!) had the downstream effect of an equivalent surge in downstream log entries. Earlier technical challenges contributed to this surge of new entries as engineers worked overtime to add diagnostics to our platform (see our previous <a href="https://blog.coinbase.com/how-were-scaling-our-platform-for-spikes-in-customer-demand-4a047cb3139c">scaling blog post</a> for more detail). During this period, a single Coinbase API call could generate up to 100 separate log entries, at times resulting in terabytes of log data per hour.</p><p>The cluster became unwieldy. As the size of the engineering team increased dramatically, the combined weight of terabytes per day of logs, a monolithic cluster, and unrestricted access patterns led to outages that halted engineering productivity and created operational hurdles.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*iXcuRQhFV8XjjE36" /><figcaption>The logs experience for engineers during Elasticsearch outages.</figcaption></figure><p>It became clear that a monolithic Elasticsearch cluster would not be sufficient for our observability needs. Some of our problems included:</p><ul><li>A single bad Kibana query (hello, Timelion) could cause a hiccup severe enough to affect the entire engineering organization.</li><li>Certain issues were difficult to diagnose or prevent — Elasticsearch, Kibana and X-Pack lack the ability to analyze slow/expensive queries by user nor the controls to prevent expensive queries like multi-week aggregations.</li><li>Many of Elasticsearch’s load-related failure conditions (like a series of very expensive queries) would leave the cluster in a disabled state even after load had entirely subsided. Our only recourse to recover from these crippled states was to perform a full cluster restart.</li><li>Elasticsearch does not have a separate management interface, meaning that during failures we would be unable to perform basic diagnostics on the cluster. Opening a support request with Elastic requires diagnostic dumps that we were unable to generate until the cluster had recovered.</li><li>Alerting on data stored in Elasticsearch data was not intuitive — tools like Elastalert and Watcher don’t allow engineers to interactively build alerts and were difficult to integrate with PagerDuty and Slack.</li><li>We were forced to reduce log retention to reduce the impact of massive queries and speed up cluster recovery following failures.</li><li>Aside from application server standard output, we were also storing and querying security data like AWS VPC Flow Logs and Linux Auditd records which required separate security controls and exhibited different performance characteristics.</li><li>Our two largest internal applications consumed 80–90% of our log pipeline capacity, reducing the performance and retention for other smaller applications in our environment.</li></ul><p>We chose to solve these problems in two ways:</p><ol><li>Introduce a new platform to provide engineers with features that are impractical to provide with Elasticsearch (namely inexpensive aggregations, alerting, and downsampling for long retention).</li><li>Split our self-managed, monolithic Elasticsearch cluster into several managed clusters segmented by business unit and use case.</li></ol><h3>Metrics</h3><p>Based on our challenges self-managing Elasticsearch combined with our short experiments at developing a reliable blue-green deploy strategy for Prometheus backends influenced our decision to choose a managed service for our metrics provider. After evaluating several providers, we settled on Datadog.</p><p>Unlike log platforms which store data as discrete structured events, metric stores like Datadog store numerical values over time in a matrix of time by tag/metric value. In other words, in Datadog, if you send a single gauge or counter metric 100,000 times in a 10s period, it will only be stored once per tag value combination while on a logs platform that same value would result in 100,000 separate documents.</p><p>As a result of this tradeoff, metrics stores like Datadog allow for extremely fast aggregations and long retention at the cost of reduced granularity and cardinality. Specifically with cardinality, because every additional tag value added to a given metric requires a new column to be added to the time vs tag/metric matrix, Datadog makes it expensive to breach their 10k unique tag combination per host limit.</p><p>Despite these tradeoffs, we’ve found Datadog to be a near-perfect complement to our internal logs pipeline.</p><ul><li>Creating and iterating on alerts is fast and intuitive. Internally, we’ve built a tool to automatically monitor and codify our Datadog monitors and dashboards to prevent accidental modifications.</li><li>Pulling up complex dashboards with metrics from the past several months is guilt-free and near-instantaneous.</li><li>Features like distribution metrics allow engineers to easily understand the performance from a block of code with global percentiles.</li><li>Limitations on cardinality can be confusing for engineers who want to keep track of high cardinality values like user_id or wallet address.</li></ul><h3>Metrics vs Logs</h3><p>A common topic internally, we’ve found the distinction between Metrics and Logs to be important. At a high level the tools have similar feature sets — both allow applications to send arbitrary data which can be used to combine visualizations into fancy dashboards. However, beyond their basic feature sets, there are major differences in the features, performance, and retention of these tools. Neither tool can support 100% of use cases, so it’s likely that engineers will need to leverage both in order to provide full visibility into their applications.</p><p>In short, we think that Metrics should be used for dashboards and alerts; while Logs should be used as an investigative tool to find the root cause of issues.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/774/1*U5l_bnx5u_Y8PJ0rPiGw0Q.png" /><figcaption>An table we use internally to illustrate the difference between Logs and Metrics.</figcaption></figure><h3>Securing the Datadog Agent</h3><p>From a security perspective, we are comfortable using a third-party service for metrics, but not for logs. This is because metrics tend to be numeric values associated with string keys and tags, compared to logs which contain entire lines of standard output.</p><p>Datadog offers operators a series of tight integrations — if you provide the Datadog agent access to a host’s /proc directory, Docker socket, and AWS EC2 metadata service, you’ll be provided rich metadata and system stats attached to every metric you generate. Running a 3rd party agent like Datadog on every host in your infrastructure, however, carries some security risk regardless of vendor or product, so we chose to take a more secure approach to employing this technology.</p><p>We took several actions in order to gain maximum exposure to these Datadog integrations while also reducing the risk associated with running a third party agent.</p><ul><li>Rather than use the pre-built Docker container, we built our own stripped down version with as few optional third party integrations as possible.</li><li>By default, the agent is opt-in — projects need to explicitly choose to allow the Datadog container.</li><li>On every host, put the container on a separate “untrusted” network bridge without access to other containers on the host, our VPC, or the EC2 AWS metadata service. We hard code the `DD_HOSTNAME` environment to the host’s instance ID to allow the AWS integration to continue working.</li><li>Run a special Docker socket proxy service on hosts to enable the Datadog container integration without exposing the container’s potentially secret environment variable values.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*D8MMnv20RCsRUfgv" /><figcaption>An overview of how we lock down the local Datadog agent.</figcaption></figure><h3>Logs</h3><p>Developing a strong metrics foundation at Coinbase helped to alleviate some of the problems we experienced with Elasticsearch as many workloads naturally migrated to Datadog. Now at least when an issue did occur on the monolithic cluster, engineers had data they could fall back on.</p><p>But the Elasticsearch issues and outages continued. As engineer headcount continued to grow, logging continued to be a source of frustration. There were about 7 new engineering productivity impeding incidents in Q4 2018. Each incident would require operational engineers to step through elaborate runbooks to shut down dependent services, fully restart the cluster, and backfill data once the cluster had stabilized.</p><p>The root cause of each incident was opaque — could it be a large aggregation query by an engineer? A security service gone rouge? However the source of our frustration was clear — we’d jammed so many use cases into this single Elasticsearch cluster that operating and diagnosing the cluster had become a nightmare. We needed to separate our workloads in order to speed incident diagnosis and reduce the impact of failures when they did occur.</p><p>Functionally sharding the cluster by use case seemed like a great next step. We just needed to make a decision between investing further in the elaborate automation we’d put in place to manage our existing cluster, or reapproach a managed solution to handle our log data.</p><p>So we chose to reevaluate managed solutions for handling our log data. While we’d previously decided against using Amazon Elasticsearch Service due to what we considered at the time to be a limited feature set and stories of questionable reliability, we found ourselves intrigued by its simplicity, approved vendor status, and AWS ecosystem integration.</p><p>We used our <a href="https://blog.coinbase.com/codifying-coinbase-6262e3e664ca">existing codification framework</a> to launch several new clusters. Since we leverage AWS Kinesis consumers to write log entries to Elasticsearch, simply launching duplicate consumers pointed at the newly launched clusters allowed us to quickly evaluate the performance of Amazon Elasticsearch Service against our most heavy workloads.</p><p>Our evaluation of Amazon Elasticsearch Service went smoothly, indicating that the product had matured significantly over the past two years. Compared to our previous evaluation, we were happy to see the addition of instance storage, the support of modern versions of Elasticsearch (only a minor version or two behind at most), as well as various other small improvements like instant IAM policy modification.</p><p>While our monolithic cluster relied heavily on X-Pack to provide authentication and permissions for Kibana. Amazon Elasticsearch Service relies on IAM to handle permissions at a very coarse level (no document or index level permissions here!). We were able to work around this lack of granularity by dividing the monolith into seven new clusters, four for the vanilla logs use case, and three for our various security team use cases. Each cluster’s access is controlled by leveraging a cleverly configured nginx proxy and our existing internal SSO service.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Y2hWxi32QUfk36F5" /><figcaption>“Kibana Selector” — our way of directing engineers to the appropriate functionally sharded cluster.</figcaption></figure><p>Migrating a team of over 200 engineers from a single, simple to find Kibana instance (kibana.cb-internal.fakenet) to several separate Kibana instances (one for each of our workloads) presented a usability challenge. Our solution is to point a new wildcard domain (*.kibana.cb-internal.fakenet) at our nginx proxy, and use a project’s Github organization to direct engineers the appropriate Kibana instance. This way we can point several smaller organizations at the same Elasticsearch cluster with the option to split them out as their usage grows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_3iKzxCFD8j_B3Ci" /><figcaption>Our current log pipeline architecture overview.</figcaption></figure><p>Functionally sharding Elasticsearch has not only had a massive impact on the reliability of our logging pipeline, but has dramatically reduced the cognitive overhead required by the team to manage the system. In the end, we’re thrilled to hand over the task of managing runbooks, tooling, and a fickle Elasticsearch cluster to AWS so that we can focus on building the next generation of observability tooling at Coinbase.</p><p>Today, we’re focusing on building the next generation of observability at Coinbase — if these types of challenges sound interesting to you, we’re hiring <a href="https://www.coinbase.com/careers/positions/1307281">Reliability Engineers</a> in San Francisco and Chicago (see <a href="https://www.youtube.com/watch?v=YDr1_-Tttz0">our talk at re:invent </a>about the types of problems the Reliability team is solving at Coinbase). We have many other positions available in San Francisco, Chicago, New York, and London — visit our careers page at <a href="http://coinbase.com/careers">http://coinbase.com/careers</a> to see if any positions spark your interest!</p><p><em>This website may contain links to third-party websites or other content for information purposes only (“Third-Party Sites”). The Third-Party Sites are not under the control of Coinbase, Inc., and its affiliates (“Coinbase”), and Coinbase is not responsible for the content of any Third-Party Site, including without limitation any link contained in a Third-Party Site, or any changes or updates to a Third-Party Site. Coinbase is not responsible for webcasting or any other form of transmission received from any Third-Party Site. Coinbase is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement, approval or recommendation by Coinbase of the site or any association with its operators.</em></p><p><em>Unless otherwise noted, all images provided herein are by Coinbase.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=13196b15edb7" width="1" height="1" alt=""><hr><p><a href="https://medium.com/the-coinbase-blog/logs-metrics-and-the-evolution-of-observability-at-coinbase-13196b15edb7">Logs, metrics, and the evolution of observability at Coinbase</a> was originally published in <a href="https://medium.com/the-coinbase-blog">The Coinbase Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How we're scaling our platform for spikes in customer demand]]></title>
            <link>https://medium.com/the-coinbase-blog/how-were-scaling-our-platform-for-spikes-in-customer-demand-4a047cb3139c?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/4a047cb3139c</guid>
            <category><![CDATA[mongodb]]></category>
            <category><![CDATA[coinbase]]></category>
            <category><![CDATA[ruby]]></category>
            <category><![CDATA[scaling]]></category>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Mon, 06 Aug 2018 22:35:16 GMT</pubDate>
            <atom:updated>2018-08-07T00:18:53.175Z</atom:updated>
            <content:encoded><![CDATA[<h3>How we’re scaling our platform for spikes in customer demand</h3><p>In 2017, the world saw an explosion in the popularity of cryptocurrency, and the ecosystem’s total market cap jumped from $20 billion to $600 billion. During this time, almost every component of Coinbase’s technology was battle-tested, and it showed our team that we need to focus on the reliability and scalability of our platform, just like we do with security. At MongoDB World 2018, myself, Michael de Hoog, and Jordan Sitkin, all engineers at Coinbase, gave a talk about the lessons we learned in 2017 and how we’re scaling our platform now. You can <a href="https://www.youtube.com/watch?v=i6ws1JpvNs0">watch the talk here</a> or read our recap below.</p><h3>Lessons learned from 2017</h3><p>Our traffic patterns in 2016, the year before the explosion in cryptocurrency popularity, had been remarkably consistent. Ahead of this boom, if we had drawn a red line where we expected our platform to experience issues, we would have put it somewhere around four or five times our typical daily maximum traffic of about 100,000 backend API requests per minute.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Vv81svzbm6FoD0L7" /><figcaption>Here’s a quick look at backend requests per minute in 2016 before the price of ether skyrocketed.</figcaption></figure><p>However, in May and June of 2017, the price of ether skyrocketed and traffic exploded past that red line. There were several days during this period where we experienced sustained traffic in this red zone, during which we experienced periods of downtime.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3NSrfxrUL1IQctQ8" /><figcaption>During the early heavy traffic period in 2017, here’s what backend requests per minute looked like.</figcaption></figure><p>To solve these scalability issues fast, the Coinbase engineering team started by focusing on the low-hanging fruit in our environment. We worked around the clock to perform tasks like vertically scaling, upgrading database versions to take advantage of performance improvements, optimizing indexes, and splitting out hotspot collections into their own clusters. Each of these improvements bought us headroom, but these low-hanging fruit were beginning to dry up, and traffic was continuing to climb.</p><p>During each outage, the pattern was the same: our primary monitoring platform would show a 100x spike in latency, along with a strange 50/50 split between Ruby and MongoDB time. As our primary datastore, it made sense that MongoDB time would experience this high-latency during periods of heavy traffic, but the Ruby time wasn’t adding up.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*01Kngli8RtbnnOE5" /><figcaption>In earlier monitoring systems, this is how “the Ghost” appeared.</figcaption></figure><p>We affectionately began to refer to this issue as “the Ghost,” as our existing monitoring tools were unable to provide clear answers to some of our most critical questions. Where were these queries coming from? What did they look like? Why was there a correlated spike in Ruby time? Could the issue be originating on the application side?</p><p>Simply put, our existing monitoring services were not able to utilize all of the context available to us inside our environment. We needed a framework for answering and visualizing the relationships between our environment’s components.</p><p>We began to further instrument database queries by modifying MongoDB’s database driver to log all queries above a certain response time threshold, along with important context like the request/response size, response time, source line of code, and query shape.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pTwkr1YQdGJsGsqc" /><figcaption>Here’s a glance at the important context to be logged on all slow MongoDB queries.</figcaption></figure><p>Our improved instrumentation provided us detailed data that allowed us to quickly narrow in on some strange characteristics that were present, even during non-outage situations. The first major outlier we saw was an extremely large response size object originating from a device find query. These massive queries would result in a massive network load when our users would sign in to make purchases or view the dashboard.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FwZsdng1ZF5m21rS" /></figure><p>The reason for this extremely large response size was that we had modeled the relationship between the <em>users</em> and <em>device</em> <em>classes</em> as a many-to-many relationship. For example, some users might have multiple devices, while some devices may have multiple users. A poor device fingerprinting algorithm had bucketed a huge number of users into the same device, resulting in a single device object with a massive array of user_ids.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/804/0*EHNd9qK9uGNm69ac" /></figure><p>To solve the issue, we refactored this relationship to simply be a one-to-many relationship, where each device maps to just a single user. The performance impact was dramatic and gave Coinbase its single biggest performance boost in 2017.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*J7w4rKgGeTHnIMC9" /></figure><p>This finding illustrated the power of good monitoring. Before granularly instrumenting our database queries, this was a near-impossible issue to debug. With the new tools, it was now obvious.</p><p>Another issue we set out to solve was large read throughput on certain collections. We decided to add a query-caching layer that would cache query results in Memcached. Any single document queries on certain collections would first query the cache before querying the database, and any database writes would also invalidate the cache.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*XxVTWHqgw2YLhCM0" /></figure><p>We were able to roll out this change across a number of database clusters simultaneously. The query cache was written at the ORM and driver level, which allowed us to affect multiple problematic clusters at once.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ots-w_lrAqtQiyH6" /></figure><p>As it turns out, the massive surge in traffic we experienced in May and June was nothing compared to the surge we experienced just a few months later in December and January. With the help of these fixes and others, we were able to withstand even larger surges in traffic.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oaiYgfvBjWZD9jK0" /><figcaption>The spike from early 2017 is just a blip compared to December and January</figcaption></figure><h3>Preparing for the future</h3><p>Today we’re proactively working to make sure we’re prepared for the next surge in cryptocurrency interest. While it was easy to work on these improvements during the heat of a real firefight, we needed to find a way to improve our future performance, even during lower periods of traffic. The obvious answer is to load test our environment by emulating traffic patterns at several times the levels we experienced in the past to discover where our next weak point could originate.</p><p>Our chosen solution is to perform traffic capture and playback, specifically on our databases, to generate artificial “crypto mania” on demand. For us, this method is preferable to synthetic traffic generation, since it removes the requirement to keep synthetic scripts up to date. Every time we run the suite, we’ll be sure the queries map exactly the type of traffic our application is producing, based on our captured data.</p><p>To do this, we built a tool called Capture, which wraps an existing tool called mongoreplay. After choosing a specific cluster in our environment, Capture simultaneously kicks off a disk snapshot and begins to capture raw traffic on our application servers directed to that cluster. It then saves encrypted versions of these captures to S3 playback at a later time. When we’re ready to perform the playback, another tool called Cannon, based on mongoreplay, plays back the recorded traffic to a freshly launched cluster based on the previous cluster snapshot.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*UNvDf6Ow6UOAFQfO" /></figure><p>One challenge we faced is how to capture all of the MongoDB traffic for a single cluster across several application servers simultaneously. Cannon solves this by opening a 10MB buffer from each capture to simultaneously merge and filter the captures.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dVS4KOIb-VhBVqVt" /></figure><p>The final result is one merged capture file which can then be targeted by Cannon toward a freshly launched MongoDB cluster. Cannon allows you to choose exactly the speed to replay the capture in order to simulate loads thousands of times larger than what we may be experiencing on any given day.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4oEnsxBfjdI3saJL" /></figure><p>We’re just getting started with Capture and Cannon and are excited to see the types of discoveries we find as we perform these types of load tests on all of our MongoDB clusters.</p><p>One major discovery as a result of our work with Capture and Cannon comes from one of Cannon’s debug features. Cannon has the ability to inspect a specific capture file and see the first 100 messages in it. Upon inspection, we noticed something interesting:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*va93fpUYp2wiTzsc" /></figure><p>Notice the ping commands intermingled with the finds? Turns out that the MongoDB Ruby driver was not correctly following the MongoDB driver spec and was performing a ping command (to check replica set state) alongside each query to the database. While this behavior was unlikely to have been <em>causing</em> our downtime related issues, it was almost certainly the cause of the “ghost-like” behavior we observed in our monitoring.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*N963U8t3J5323DsS" /></figure><p>After all the effort put into tackling these challenges, we’re proud of the current state of reliability at Coinbase. The events of 2017 reaffirm that a customer’s ability to access and view their funds is critical to our ability to fulfill our goal to be the most trusted place to buy, sell, and manage cryptocurrency. While security has always been our number one priority, we’re excited to focus on ensuring that the reliability of our platform is a top priority too!</p><p>We’ve formed three separate performance and reliability specific teams to prepare for future waves of cryptocurrency enthusiasm. If you’re interested in these types of challenges, please <a href="https://www.coinbase.com/careers">visit our careers page</a>!</p><p><em>Except where noted herein, the images displayed are from Coinbase.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4a047cb3139c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/the-coinbase-blog/how-were-scaling-our-platform-for-spikes-in-customer-demand-4a047cb3139c">How we&#39;re scaling our platform for spikes in customer demand</a> was originally published in <a href="https://medium.com/the-coinbase-blog">The Coinbase Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[December 12th Post Mortem]]></title>
            <link>https://medium.com/the-coinbase-blog/december-12th-post-mortem-c1c010824f42?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/c1c010824f42</guid>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[coinbase]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[bitcoin]]></category>
            <category><![CDATA[litecoin]]></category>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Fri, 15 Dec 2017 16:01:01 GMT</pubDate>
            <atom:updated>2018-11-27T23:06:13.581Z</atom:updated>
            <content:encoded><![CDATA[<p>Over the past month, Coinbase has continued to prioritize scaling our backend systems so that we can provide a reliable customer experience during periods of high traffic. Despite our improvements, on December 12th, all time high levels of traffic lead to periods of slowness and elevated error rates.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/894/0*_8ZwGWS6av7fLFiM." /></figure><p>On December 11th at 22:00 PST Coinbase underwent scheduled maintenance to improve database performance. One of the techniques we utilized during this maintenance window was to distribute database load by splitting existing datasets to new clusters.</p><p>On December 12th, starting at 04:00 PST, traffic began to climb as a result of large Litecoin price movements. At 04:15 PST, two of the new clusters from the maintenance window began to experience slowness as a result of the slower network attached disks used by these instances to complete the migration. This database slowness resulted in elevated response times and high error rates. We were able to resolve these issues by 05:42 PST by failing over to high performance nodes which we had begun provisioning the night before.</p><p>Following these improvements, site traffic continued to climb, reaching all time high levels by 06:14 PST. Starting at 05:58 PST, one of our primary clusters began to experience degraded performance as a result of overwhelming query volume. We worked throughout the day to reduce pressure on this cluster by deploying application level improvements to more efficiently cache database queries. By 14:00 PST services were fully restored.</p><p>Scaling is hard, but we’re working hard to support the millions of people who are discovering cryptocurrency for the first time. We are looking to hire senior backend engineers in San Francisco, London and New York. If working on this sort of challenge excites you please see <a href="https://www.coinbase.com/careers">our careers page</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c1c010824f42" width="1" height="1" alt=""><hr><p><a href="https://medium.com/the-coinbase-blog/december-12th-post-mortem-c1c010824f42">December 12th Post Mortem</a> was originally published in <a href="https://medium.com/the-coinbase-blog">The Coinbase Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[December 6th-7th Post Mortem]]></title>
            <link>https://medium.com/the-coinbase-blog/december-6th-7th-post-mortem-9dddb0bba130?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/9dddb0bba130</guid>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[bitcoin]]></category>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[coinbase]]></category>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Sat, 09 Dec 2017 01:05:10 GMT</pubDate>
            <atom:updated>2018-11-27T23:00:25.470Z</atom:updated>
            <content:encoded><![CDATA[<p>Over the past week, Coinbase has continued to invest significant resources into scaling our backend systems to provide a reliable customer experience during periods of high traffic. Despite these efforts to scale, the continued rise of legitimate user traffic lead to periods of slowness and downtime over the course of December 6th and December 7th. The chart below shows the relative change in Coinbase traffic from <a href="https://engineering.coinbase.com/november-29th-december-1st-post-mortem-69a1810f9910">our incident last week</a> and the peak traffic period this week.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n-MJwbLA-JdNDgEpM-4Q1Q.png" /></figure><h3>December 6th</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xq35QLSe3aC8zJ0q." /></figure><p>On December 6th, Coinbase continued to experience high traffic as a result of large Bitcoin price movements. At 12:22 PST, one of our primary MongoDB clusters began to experience degraded performance leading to elevated response times across all API endpoints. We attributed this slowness to saturation of the storage engine’s concurrency mechanisms as a result of poor disk performance. Earlier in the day, we began the process of upgrading the hardware of several of our most important databases (including this saturated MongoDB cluster) as part of our ongoing efforts to scale Coinbase’s backend databases. At 13:13, we successfully completed the process of upgrading this database to an instance type with significantly faster instance storage.</p><p>By 13:25 PST, services were fully restored. We are continuing the process of upgrading all of our databases to prepare for further periods of high traffic.</p><h3>December 7th</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/941/0*EFW3_5uwGOaGs5B0." /></figure><p>On December 7th, starting at 07:10 PST Coinbase began to experience extreme levels of traffic as a result of a rapid Bitcoin price movements. Starting at 07:20 PST this traffic began to bottleneck behind one of our primary database clusters, even though that cluster had been upgraded on December 6th. This resulted in elevated response times and periods of downtime. Over the course of the next several hours, we took several steps to reduce web requests and better cache queries to this cluster, yielding small improvements in usability.</p><p>At 13:55 PST, it became apparent that the cluster was suffering from a bottleneck in memory management, which lead us to alter lower level configuration to better utilize the upgraded resources. This yielded a significant improvement in query performance under the high concurrency we had been experiencing. By 14:00 PST services were fully restored.</p><p>Scaling is hard, but we’re eager to to help solve this surge of interest! We are looking to hire senior backend engineers in San Francisco, London and New York. If working on this sort of challenge excites you please see <a href="https://www.coinbase.com/careers">our careers page</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9dddb0bba130" width="1" height="1" alt=""><hr><p><a href="https://medium.com/the-coinbase-blog/december-6th-7th-post-mortem-9dddb0bba130">December 6th-7th Post Mortem</a> was originally published in <a href="https://medium.com/the-coinbase-blog">The Coinbase Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[November 29th-December 1st Post Mortem]]></title>
            <link>https://medium.com/the-coinbase-blog/november-29th-december-1st-post-mortem-69a1810f9910?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/69a1810f9910</guid>
            <category><![CDATA[scaling]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[coinbase]]></category>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[bitcoin]]></category>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Tue, 05 Dec 2017 18:01:00 GMT</pubDate>
            <atom:updated>2018-11-27T23:02:19.016Z</atom:updated>
            <content:encoded><![CDATA[<p>Over the past year, Coinbase has invested significant effort to improve the scalability of our systems during periods of peak traffic. Despite these efforts, Coinbase experienced slow response times and intermittent downtime due to increased user traffic on November 29th, November 30th, and December 1st. These issues were largely the result of two undersized and over-utilized database clusters. Over the course of these three days and a period of scheduled maintenance, Coinbase engineers were able to remediate these issues by reducing total query volume and scaling the affected databases.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WFOpLOTRPFthlTNF." /><figcaption>Relative traffic before and after the incident.</figcaption></figure><p>The objective of this post is to provide a technical overview of the challenges we faced last week and actions we took to restore services to normal as quickly as possible.</p><h3>November 29th</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*VIzMAI_EbF7ml9od." /></figure><p>On November 29th, at 05:03 PST, Coinbase experienced a large increase in user traffic during due to large price movements in Bitcoin and Ethereum. As a result, one of our primary MongoDB clusters experienced CPU saturation leading to elevated response times across all API endpoints. These elevated response times resulted in saturated application queues which caused intermittent 502s for customers on both the Coinbase website and mobile apps.</p><p>To mitigate the database saturation, we worked to cache specific queries and reduce the load on the affected database. At 06:24 PST we began the process of vertically scaling the affected MongoDB cluster to new instance types with double the capacity. By 08:50 PST, site performance had been restored to normal.</p><p>Traffic levels continued to climb, and at 10:49 PST one of our primary Redis servers began to experience CPU saturation as a result of a series of expensive queries. To alleviate the issue, we developed fixes to help alleviate the pressure on this Redis cluster. By 13:25 PST the fixes, combined with slightly lower traffic, reduced CPU pressure to allow traffic to be served at normal response times. By 15:00 PST services were fully restored and operating normally.</p><p>At 20:10 PST we announced planned maintenance for November 30th at 23:00 PST. The purpose of this maintenance was to increase capacity by splitting both of the affected databases (MongoDB and Redis) into three new and separate clusters.</p><h3>November 30th</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Hcf_xhTZSK-bGz8k." /></figure><p>On November 30th, starting at 05:30 PST Coinbase again began to experience elevated response times and intermittent 502s as a result of high traffic induced CPU saturation on our primary Redis cluster. Over the course of the downtime, we attempted to improve the performance of the cluster by analyzing analyzing Redis commands and pruning unnecessary query volume.</p><p>By 08:25 PST site performance was back to normal as a result of these Redis fixes and reduced overall site traffic.</p><p>At 23:00 PST, we began our scheduled maintenance. During this maintenance, we were able to evenly split out collections from our above mentioned MongoDB cluster across several new replica sets. Additionally, we took improved Redis performance by dividing up the misbehaving cluster’s keys across several new clusters.</p><h3>December 1st</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1YGa7HZrPdVXQTca." /></figure><p>On December 1st, at 04:00 PST Coinbase began to experience elevated response times as a result of network saturation on one of the newly upgraded Redis clusters. During the November 30th planned maintenance, one of the newly split-out clusters had been inadvertently created with an undersized network interface (“Up to 10 Gbps” instead of “10 Gbps”).</p><p>Over the course of the morning (04:00–13:10 PST) Coinbase worked to identify the reason for the poorly performing database. During this period, Coinbase experienced intermittent periods of downtime — each period lasting between 3 and 7 minutes. At 13:07 PST the decision was made to accept 30 to 60 minutes of full downtime starting at 13:10 PST to upgrade the poorly performing database in order to resolve the elevated response times.</p><p>By 13:40 PST the new Redis cluster with higher network capacity became operational. At 14:10 PST Coinbase became fully operational in all countries. Later that day, we resolved the network saturation by identifying a query pattern which had been returning very large response bodies.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*taXvYuttof1tjLr6." /><figcaption>Redis NetworkBytesOut before and after tracking down the bad query pattern.</figcaption></figure><p>We are hiring senior backend engineers in San Francisco, London and New York. If working on this sort of challenge excites you please see <a href="https://www.coinbase.com/careers">our careers page</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=69a1810f9910" width="1" height="1" alt=""><hr><p><a href="https://medium.com/the-coinbase-blog/november-29th-december-1st-post-mortem-69a1810f9910">November 29th-December 1st Post Mortem</a> was originally published in <a href="https://medium.com/the-coinbase-blog">The Coinbase Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[May 22–24 Downtime Post Mortem]]></title>
            <link>https://medium.com/the-coinbase-blog/may-22-24-downtime-post-mortem-2031b47c82ec?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/2031b47c82ec</guid>
            <category><![CDATA[mongodb]]></category>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Wed, 14 Jun 2017 18:39:58 GMT</pubDate>
            <atom:updated>2018-11-27T23:04:29.385Z</atom:updated>
            <content:encoded><![CDATA[<p><em>During the week of May 22, Coinbase didn’t meet customer expectations. We were down for extended periods and slow in others. This is a technical post-mortem of the events of that week. We are investing significant resources to make our systems scale with the next 10x growth in traffic.</em></p><p>On May 22, Coinbase started experiencing sustained high user traffic as a result of large Bitcoin and Ethereum price fluctuations. Over the next week, our low points in traffic far exceeded previous peaks in the preceding months. As a result, we bumped up against a series of capacity limits which led to long stretches of performance degradation and periods of full-site downtime.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*07uy4Mxb-6a3ENBab5nxug.png" /><figcaption>Request traffic on our primary load balancer (incident highlighted).</figcaption></figure><h3>MongoDB</h3><p>On the first day of the incident (May 22), unoptimized database queries and a handful of missing indices on our primary MongoDB instances compounded, leading to a surge in database queues and degraded performance across coinbase.com. We were able to restore full service and solve our database queues by building key indices and optimizing expensive application queries.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yctwZhCBiq986T_dPp4Tyw.png" /><figcaption>NewRelic web transaction times during the incident.</figcaption></figure><p>On the second day of the incident (May 23), the MongoDB query planner for our clusters began to exhibit poor query selection under high load, resulting in query times several orders of magnitude slower than identical queries run on the correct index. This poor query selection led to short, intermittent downtime periods during which database queues would rise rapidly until the poorly-planned query completed.</p><p>To resolve these query planning issues, we spent the next 24 hours (May 23 — May 24) performing major MongoDB version upgrades, bringing all of our primary clusters up to version 3.0. We had been preparing to do these upgrades for weeks, and in consultation with MongoDB experts we decided to move forward under heavy load with the hope of mitigating these query planning issues. The upgrades to 3.0 proceeded smoothly despite the load and lead to drastic improvements in query planning and performance across the board, resolving our MongoDB issues for the duration of the incident.</p><p>In the weeks since the incident, we’ve worked hard to bring our MongoDB clusters up to date, and as of June 12 have successfully upgraded all of our clusters to version 3.2 with the new WiredTiger storage engine. In total over a period of three weeks we migrated 10 MongoDB clusters from a mix of 2.4 and 2.6 and have seen dramatically increased query performance and consistency.</p><h3>Redis</h3><p>As traffic continued to reach new heights on the third day of the incident (May 24), we hit the capacity limit of our primary Redis ElastiCache cluster. Due to the single-threaded design of Redis, we became CPU bound on one core which we fully saturated with over 20,000 requests per second.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*d2aBD1tD1kJauSC3." /><figcaption>Redis ElastiCache Cluster (line: single CPU threshold).</figcaption></figure><p>Over the next day, we were able to restore service through a combination of improving expensive queries, sharding existing queries across multiple logically separated new instances, and reducing the total volume of queries within the application by 40%. By May 25 at 19:00 PST we were able to restore and maintain full service across our infrastructure.</p><h3>Going Forward</h3><p>We are committed to improving site performance so that we can serve our customers during even the most volatile periods in cryptocurrency.</p><p>We are rapidly expanding our team, if you are interested in solving challenges like these, <a href="https://www.coinbase.com/careers">we’re hiring</a>!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*spYa1N7nPvfEtR2Z." /><figcaption>Google Trends interest in Bitcoin and Ethereum during the incident.</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2031b47c82ec" width="1" height="1" alt=""><hr><p><a href="https://medium.com/the-coinbase-blog/may-22-24-downtime-post-mortem-2031b47c82ec">May 22–24 Downtime Post Mortem</a> was originally published in <a href="https://medium.com/the-coinbase-blog">The Coinbase Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Codifying Coinbase]]></title>
            <link>https://medium.com/the-coinbase-blog/codifying-coinbase-6262e3e664ca?source=rss-8dcf8e219b0b------2</link>
            <guid isPermaLink="false">https://medium.com/p/6262e3e664ca</guid>
            <dc:creator><![CDATA[Luke Demi]]></dc:creator>
            <pubDate>Thu, 04 May 2017 12:01:01 GMT</pubDate>
            <atom:updated>2018-11-27T23:04:44.894Z</atom:updated>
            <content:encoded><![CDATA[<p>The Infrastructure Team at Coinbase has the goal of enabling any engineer in the company to quickly and securely deploy complex infrastructure. This effort started with our secure deployment pipeline <a href="https://blog.coinbase.com/scaling-developer-productivity-d23ce491f869">Codeflow</a>, was extended by our codification tooling <a href="https://maori.geek.nz/treat-infrastructure-like-you-treat-code-e5b3c0ad925d">GeoEngineer</a>, and stress tested by our 24 hour whole-infrastructure rolling exercise <a href="https://youtu.be/3lkecchwxc4?t=36m21s">Scorched Earth</a>.1</p><p>Our latest project to empower engineers was to codify <em>all</em> of our infrastructure with the goal of allowing <em>any</em> engineer in our organization to propose changes in a secure, consistent manner.</p><h3>Choose the Right Tool</h3><p>Prior to this project, the majority of our infrastructure <em>was</em> codified, although using different tools and different standards. As our clouds evolved in complexity, we ran into the shortcomings of our existing tools and experimented with a variety of ways to scale our effort:</p><ul><li><strong>CloudFormation</strong> — Core infrastructure at Coinbase (e.g. VPCs, route tables, VPN configuration) as well as IAM policies were codified using CloudFormation. While this originally worked for our first application of the CloudFormation templates, CloudFormation’s weak ability to <em>plan</em> or <em>review</em> changes led us to fall back to manual changes and let these templates fall out of sync.</li><li><strong>Terraform</strong> — Next, we started to work with Terraform for newer services, however due to <a href="https://medium.com/@b_radlarson/c3bf644c31d0">shortcomings</a> with the tool, we never committed fully and were left with a mix codified and manual configured resources, (along with a lot of state files across our AWS accounts).</li><li><strong>GeoEngineer</strong> — To work around the aforementioned shortcomings in Terraform, we began developing <a href="https://maori.geek.nz/treat-infrastructure-like-you-treat-code-e5b3c0ad925d">GeoEngineer</a>. As a result, many of our core apps deployed by Codeflow had already been codified using GeoEngineer.</li></ul><p>After evaluating the above options as well as Ansible and SaltStack, we decided to double down on our GeoEngineer building upon Terraform’s power.</p><h3>Picking a Metric</h3><p>Leading into this project we validated GeoEngineer with well defined <a href="https://benchmarks.cisecurity.org/downloads/show-single/index.cfm?file=awsthreetier.100">3-tier-applications</a>. This helped eliminate obvious bugs but we still had the large task of codifying existing and bespoke cloud resources. Our largest deployments often contained new, complex services like replicated Elasticache clusters, multiple encrypted S3 buckets for temporary storage and more.</p><p>Given that GeoEngineer has insight into all of the resources, codified or not, that exist in your infrastructure, we were able to use geo status to produce the exact percentage of codified versus uncodified resources in our infrastructure. Selecting and reinforcing this metric as our north star during the project made it simple to keep track of our progress towards 100%.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YTqtIIPnbdMbk7c8UQ8qWg.png" /><figcaption>Codification progress over the course of the project</figcaption></figure><p>Along with returning the resource codification percentage, geo status returns a list of uncodified resources which we were then able to reference as a primary source during our effort. This output made collaboration easy, since it was never difficult to determine which resources to tackle next.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b0e445b4a6e9c2f632d98438043de403/href">https://medium.com/media/b0e445b4a6e9c2f632d98438043de403/href</a></iframe><p>As a secondary metric, we utilized CloudTrail data to visualize the level of automation as <em>Human</em> (using dashboard) vs <em>Computer</em> (geo apply) actions. As a company with a deep focus on security, reducing the number of humans capable of taking actions, as well as reducing the total number of actions that those humans take, helps to reduce our exposure to both mistakes and malicious intent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/696/1*h_BiPysin3kgW3t0vVAR7g.png" /><figcaption>An example of a visualization on our automation dashboard.</figcaption></figure><h3>Tag Everything</h3><p>At Coinbase, we use AWS tags to categorize, document, and define ownership of our infrastructure. Resource codification was the perfect opportunity to rethink our tag standards and ensure that all of our resources are properly classified.</p><p>Using GeoEngineer, we are able to implement resource level validations to require that any resources codified in our infrastructure upholds our tag standards. An example of standardized tags we use to classify our resources are Name, ProjectName, and Org which correlate respectively to the name of the specific resource, the project it is associated with, and the project’s organization within Coinbase.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eeabbe0c85bb84e753ebc8c8ee757b41/href">https://medium.com/media/eeabbe0c85bb84e753ebc8c8ee757b41/href</a></iframe><p>Additionally, GeoEngineer can be expanded to automatically add default tags based on the context of resources.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4fa24acddc8bb659709df1eae10fc15e/href">https://medium.com/media/4fa24acddc8bb659709df1eae10fc15e/href</a></iframe><p>Beyond classification, we use tags for determining the importance of a resource and directing notifications to the right channel. For example, our pd_channel tag ensures that if reliability with a resource can’t be auto remediated that we’re sending PagerDuty alerts to the right team.</p><h3>Eliminate Cruft</h3><p>As our codified effort illuminated not just some, but all of the resources within our infrastructure, we began to find dated configurations and even long-since deprecated resources. These ‘<a href="https://en.wikipedia.org/wiki/Shadow_IT">cruft</a>’ resources are unused or unidentified resources which have been created by hand through the console or lost over time. Cruft resources are bad because not only because they’re an extra expense, but because unknown resources can lead to security holes or improper utilization.</p><p>Tackling cruft in your infrastructure can be a tedious process. One mislabeled SQS topic could actually be <strong>the</strong> SQS topic and inadvertently removing or modifying such a topic might take down an entire segment of the organization. Our technique to tackle this cruft began by using the output of geo status to list every single uncodified resource on a shared spreadsheet, and then carefully identifying and taking action on each resource.</p><p>We utilized three primary resources to ensure we were identifying and deleting the correct resources. First, CloudWatch’s metrics dashboard was invaluable to clarify utilization patterns for specific resources and show exactly when a resource stopped or started being used. Second, CloudTrail provided key insight into which specific user created a resource or interacted with it recently. Third, searching VPC flow logs allowed us to validate resources which hadn’t recieved any meaningful traffic.</p><p>In the end, we deleted <strong>over 270 resources</strong> across all of our environments, not including all of the resources we were able to rename and properly categorize through the effort. This was a long and tedious yet very rewarding process.</p><h3>Keep it Codified</h3><p>Our experience tells us that infrastructure codification follows the rule of entropy. No matter how hard you try, someone will want to log into the console and create or make changes to live resources. In order to protect our efforts, we want to set up the right tools and culture to keep our standards from slipping.</p><p>One of the forcing functions we utilize to prevent slippage is creating a bot called Mars to frequently run geo status and generate a percentage metric of uncodified resources that we can use to automatically generate notifications when we stray from our target.</p><p>Another strategy we use is to parse the output of geo plan to send notifications if there is a divergence between our code and the actual state of our AWS environments. This output alerts us to potential security issues like if someone were to modify an IAM policy without updating the policy file template.</p><h3>What’s Next?</h3><p>Ensuring that we’ve accounted for all of our resources is just the first step on the road to completely automating our infrastructure. One of the ideas we’re working towards next is building a bot to geo apply pull requests based on consensus to further reduce any individual’s access which following our mission to empower the breadth of engineering at Coinbase.</p><p>There’s a lot more to come - if you’re interested in being part of what we’re doing, <a href="https://www.coinbase.com/careers">we’re hiring</a>!</p><p>Thanks to Rob Witoff, Graham Jenson, Brad Larson, <a href="http://twitter.com/shanedasilva">S</a>hane da Silva, Jack Kearney!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6262e3e664ca" width="1" height="1" alt=""><hr><p><a href="https://medium.com/the-coinbase-blog/codifying-coinbase-6262e3e664ca">Codifying Coinbase</a> was originally published in <a href="https://medium.com/the-coinbase-blog">The Coinbase Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>