On Friday, September 15th, for a short period of time between 11:12 PDT and 11:25 PDT, customers started receiving 503 error codes in response to some SDK authentication and evaluation requests. The users were not able to toggle flags via the admin user interface during this time.
The incident occurred following an upgrade to Redis v6 from Redis v5.
The Redis instance CPU spiked at 100%, this was due to one command that execute in O(N) time complexity. As the number of keys in the database grew during the day, the commands took longer to execute. As Redis v6 was able to execute more commands in parallel the CPU became maxed out resulting in 100% usage across all cores.
The impact was that queries took so long, that feature flag requests started to time out.
The RCA below has been split into two.
Why 1 - the ff admin service started to restart
The admin services liveness probe started failing. As a result, Kubernetes started to restart the service.
Why 2 - the liveness probe started to fail
The probe uses the admin services health-check endpoint. This checks that all downstream services are available and responding. Requests to the Redis service had started to timeout.
Why 3 - the Redis health check started to fail
The Redis service was reporting 100% CPU usage. While it was processing commands there was increased latency which resulted in many calls timing out.
Why 4 - did Redis CPU spike at 100%
We recently upgraded from Redis v5 to Redis v6. Redis v6 is multi-threaded and can perform operations concurrently.
Why 5 - did running more commands concurrently increase CPU usage to 100%
One of the Redis calls used by Feature Flags CDN solution is called ‘keys’. This returns keys based on a pattern match. Although it uses a pattern match in the command, the execution time for the command increases linearly as the total number of keys in the cache increases. During the peak part of the day, as the number of keys in the cache grew, it reached the point where the command took longer than the configured timeout to return.
Why 1 - did the evaluation service start returning 503 errors
The logs indicated requests were starting to timeout. As a result, a 503 was returned.
Why 2- did requests timeout
During the authentication and evaluation flows Feature Flags makes use of Redis to cache data. This allows us to scale the service. Some of the Redis queries started to timeout.
Why 3 - did Redis call time out
The Redis service CPU had spiked at 100%. Normally if we cannot find an item in the cache we fall through to the underlying database, but in this case because the request timed out we failed to hit the underlying database to load the data.
Why 4 - did Redis CPU spike at 100%
(see why 4 from the admin service failures)
Why 5 - did running more commands concurrently increase CPU usage to 100%
(see why 5 from the admin service failures)
There are two use-cases load tested prior to release
The part of the solution that used the expensive Redis calls occurs during requests that are served out of the CDN to guarantee the requested ETag is still up to date. This typically operates over a small set of keys, so when load testing only a small set of a few thousand keys are used.
When testing evaluation calls, this normally has a cache with a few hundred thousand keys. But this flow does not use expensive Redis calls.
These flows are tested in isolation in our testing environment, but the issue only manifests when combining the two scenarios.