974 lines
136 KiB
HTML
974 lines
136 KiB
HTML
|
||
|
||
<!doctype html>
|
||
<html lang="en-US" class="h-full" data-menu-state="off" data-motion="off">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||
<meta name="keywords" content="fly, fly.io, i, elixir, docker, cdn, hosting, servers, networking, deploy app servers, close to users, postgresql clusters, heroku competitor, heroku alternative">
|
||
<meta name="description" content="Documentation and guides from the team at Fly.io.">
|
||
|
||
<title>A Foolish Consistency: Consul at Fly.io · The Fly Blog</title>
|
||
|
||
<meta name="referrer" content="origin">
|
||
<meta name="HandheldFriendly" content="True">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="msapplication-TileColor" content="#4d7cfe">
|
||
<meta name="theme-color" content="#ffffff">
|
||
|
||
<meta property="og:locale" content="en_US">
|
||
<meta property="og:url" content="https://fly.io/blog/a-foolish-consistency/">
|
||
<meta property="og:type" content="article">
|
||
<meta property="og:title" content="A Foolish Consistency: Consul at Fly.io">
|
||
<meta property="og:image" content="https://fly.io/blog/a-foolish-consistency/assets/default-books.webp">
|
||
<meta property="og:description" content="Documentation and guides from the team at Fly.io.">
|
||
<meta property="og:site_name" content="Fly">
|
||
|
||
<!-- Search metadata for Algolia -->
|
||
|
||
<meta name="twitter:site" content="@flydotio">
|
||
<meta name="twitter:creator" content="@flydotio">
|
||
<meta name="twitter:card" content="summary_large_image">
|
||
<meta name="twitter:title" content="A Foolish Consistency: Consul at Fly.io">
|
||
<meta name="twitter:image" content="https://fly.io/blog/a-foolish-consistency/assets/default-books.webp">
|
||
<meta name="twitter:description" content="Documentation and guides from the team at Fly.io.">
|
||
|
||
<link rel="shortcut icon" type="image/x-icon" href="/static/images/favicon/favicon.ico">
|
||
<link rel="apple-touch-icon" sizes="180x180" href="/static/images/favicon/apple-touch-icon.png">
|
||
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon/favicon-32x32.png">
|
||
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon/favicon-16x16.png">
|
||
<link rel="mask-icon" href="/static/images/favicon/safari-pinned-tab.svg" color="#4d7cfe">
|
||
<link rel="canonical" href="https://fly.io/blog/a-foolish-consistency/">
|
||
|
||
<style>
|
||
html:not([data-motion=on]) * {
|
||
transition: none !important;
|
||
animation: none !important;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
let resizeTimer
|
||
|
||
window.addEventListener('resize', () => {
|
||
document.documentElement.dataset.motion = 'off'
|
||
clearTimeout(resizeTimer)
|
||
resizeTimer = setTimeout(() => {
|
||
document.documentElement.dataset.motion = 'on'
|
||
}, 500)
|
||
})
|
||
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
document.documentElement.dataset.motion = 'on'
|
||
})
|
||
</script>
|
||
<style>@font-face{font-family:'Fricolage Grotesque';font-weight:100 900;font-display:block;font-style:normal;font-named-instance:'Regular';src:url(/static/fonts/fricolage-grotesque.var.woff2) format('woff2');}@font-face{font-family:'Mackinac';src:url(/static/fonts/mackinac-medium.woff2) format('woff2');font-weight:500;font-style:normal;font-display:block;}@font-face{font-family:'Mackinac';src:url(/static/fonts/mackinac-medium-italic.woff2) format('woff2');font-weight:500;font-style:italic;font-display:block;}@font-face{font-family:'Mackinac';src: url(/static/fonts/mackinac-bold.woff2) format('woff2');font-weight:700;font-style:normal;font-display:block;}@font-face{font-family:'Fragment Mono';src:url(/static/fonts/fragment-mono-regular.woff2) format('woff2');font-weight:400;font-style:normal;font-display:block;}@font-face{font-family:'Fragment Mono';src:url(/static/fonts/fragment-mono-italic.woff2) format('woff2');font-weight:400;font-style:italic;font-display:block;}</style><script>var fontsInServiceWorker=sessionStorage.foutFontsStage1Loaded&&sessionStorage.foutFontsStage2Loaded||"serviceWorker"in navigator&&null!==navigator.serviceWorker.controller&&"activated"===navigator.serviceWorker.controller.state;if(!fontsInServiceWorker&&"fonts"in document){function fetchFonts(o){return Promise.all(o.map((function(o){return document.fonts.load(o)})))}sessionStorage.foutFontsStage2Loaded?document.documentElement.className+=" wf-loaded-stage2":sessionStorage.foutFontsStage1Loaded=!0}if("fonts"in document){let o=new FontFace("Fricolage Grotesque","url('/static/fonts/fricolage-grotesque.var.woff2') format('woff2')",{weight:"100 900",style:"normal"}),t=new FontFace("Mackinac","url('/static/fonts/mackinac-medium.woff2') format('woff2')",{weight:"500"}),e=new FontFace("Mackinac","url('/static/fonts/mackinac-medium-italic.woff2') format('woff2')",{weight:"500",style:"italic"}),a=new FontFace("Mackinac","url('/static/fonts/mackinac-bold.woff2') format('woff2')",{weight:"700"}),n=new FontFace("Fragment Mono","url('/static/fonts/fragment-mono-regular.woff2') format('woff2')",{weight:"400"}),r=new FontFace("Fragment Mono","url('/static/fonts/fragment-mono-italic.woff2') format('woff2')",{weight:"400",style:"italic"});Promise.all([o.load(),t.load(),e.load(),a.load(),n.load(),r.load()]).then((o=>{o.forEach((o=>document.fonts.add(o))),document.documentElement.classList.add("wf-loaded-stage2"),sessionStorage.foutFontsStage2Loaded=!0})).catch((o=>{throw new Error(`Error caught: ${o}`)}))}(sessionStorage.foutFontsStage1Loaded&&sessionStorage.foutFontsStage2Loaded||"serviceWorker"in navigator&&null!==navigator.serviceWorker.controller&&"activated"===navigator.serviceWorker.controller.state)&&document.documentElement.classList.add("wf-loaded-stage2");</script><link rel="preload" href="/static/fonts/fricolage-grotesque.var.woff2" as="font" type="font/woff2" crossorigin/><link rel="preload" href="/static/fonts/mackinac-medium.woff2" as="font" type="font/woff2" crossorigin/><link rel="preload" href="/static/fonts/mackinac-medium-italic.woff2" as="font" type="font/woff2" crossorigin/><link rel="preload" href="/static/fonts/mackinac-bold.woff2" as="font" type="font/woff2" crossorigin/><link rel="preload" href="/static/fonts/mackinac-bold-italic.woff2" as="font" type="font/woff2" crossorigin/><link rel="preload" href="/static/fonts/fragment-mono-regular.woff2" as="font" type="font/woff2" crossorigin/><link rel="preload" href="/static/fonts/fragment-mono-italic.woff2" as="font" type="font/woff2" crossorigin/>
|
||
|
||
<link rel="stylesheet" href="/stylesheets/tailwind.css" media="screen" />
|
||
|
||
<script defer data-domain="fly.io" src="/js/events.js"></script>
|
||
|
||
<script>
|
||
window.FLY_ANALYTICS = {
|
||
posthog: { apiKey: "phc_nuaUijb3iLWut9Kbr56bSHSP4MYdeb8CFd9BgPm3LAVY", apiHost: "https://posthog.fly.io" },
|
||
google: { gtmId: "GTM-M35Q2HRQ", gaId: "G-EX6DMZ1DZV", analyticsDomain: "analytics.fly.io" }
|
||
};
|
||
</script>
|
||
<script defer src="/static/javascripts/posthog.js"></script>
|
||
<script defer src="/static/javascripts/posthog-consent.js"></script>
|
||
<template id="ph-consent-template">
|
||
<div
|
||
id="ph-consent-banner"
|
||
hidden
|
||
role="dialog"
|
||
aria-live="polite"
|
||
aria-label="Cookie notice"
|
||
class="fixed inset-x-4 bottom-4 z-50 rounded-lg border border-gray-200 bg-white p-3 text-xs leading-snug text-gray-700 shadow-lg sm:inset-x-auto sm:right-4 sm:max-w-sm sm:p-4 sm:text-sm sm:leading-relaxed dark:border-gray-700 dark:bg-gray-900 dark:text-gray-200"
|
||
>
|
||
<p class="mb-2 sm:mb-3">
|
||
<strong>Hi, it's us, Fly.io.</strong> We hate these things as much as anyone, but the
|
||
marketing gods demand conversion metrics.
|
||
</p>
|
||
<p class="mb-2 sm:mb-3">
|
||
We set analytics cookies to measure traffic and ad conversion on our marketing and docs
|
||
pages. These cookies only cover logged-out visits, never what you do in the dashboard.
|
||
</p>
|
||
<p class="mb-2 sm:mb-3">
|
||
Read all about it in our
|
||
<a href="/legal/privacy-policy" class="underline hover:text-gray-900 dark:hover:text-white">Privacy Policy</a>.
|
||
</p>
|
||
<div class="flex justify-end gap-2">
|
||
<button id="ph-consent-reject" type="button" class="rounded-md bg-gray-200 px-3 py-1.5 font-medium text-gray-800 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600">
|
||
Reject
|
||
</button>
|
||
<button id="ph-consent-accept" type="button" class="rounded-md bg-violet-600 px-3 py-1.5 font-medium text-white hover:bg-violet-700">
|
||
Accept
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<link rel="preconnect" href="https://4ET05XOQRG-dsn.algolia.net" crossorigin>
|
||
|
||
</head>
|
||
|
||
|
||
<body class="post relative w-full h-full antialiased text-gray-600">
|
||
<header
|
||
class="navbar relative z-[500] container mx-auto px-4 sm:px-6 lg:px-8 flex items-center h-24 text-navy-900 font-medium text-sm"
|
||
data-menu-container
|
||
>
|
||
<nav
|
||
id="logo"
|
||
aria-label="Logo menu"
|
||
class="relative z-[60] flex"
|
||
>
|
||
<a
|
||
href="/"
|
||
>
|
||
<svg
|
||
role="img"
|
||
class=""
|
||
fill-rule="evenodd"
|
||
viewBox="0 0 92 84"
|
||
style="pointer-events: none; width: auto; height: 36px;"
|
||
aria-labelledby="logo-title-3094 logo-description-3094"
|
||
>
|
||
<title id="logo-title-3094">Fly</title>
|
||
<desc id="logo-description-3094">App performance optimization</desc>
|
||
<g buffered-rendering="static">
|
||
<path
|
||
d="M57.413 10.134h9.454c8.409 0 15.236 6.827 15.236 15.236v33.243c0 8.409-6.827 15.236-15.236 15.236h-.745c-4.328-.677-6.205-1.975-7.655-3.072l-12.02-9.883a1.692 1.692 0 0 0-2.128 0l-3.905 3.211-10.998-9.043a1.688 1.688 0 0 0-2.127 0L12.01 68.503c-3.075 2.501-5.109 2.039-6.428 1.894C2.175 67.601 0 63.359 0 58.613V25.37c0-8.409 6.827-15.236 15.237-15.236h9.433l-.017.038-.318.927-.099.318-.428 1.899-.059.333-.188 1.902-.025.522-.004.183.018.872.043.511.106.8.135.72.16.663.208.718.54 1.52.178.456.94 1.986.332.61 1.087 1.866.416.673 1.517 2.234.219.296 1.974 2.569.638.791 2.254 2.635.463.507 1.858 1.999.736.762 1.216 1.208-.244.204-.152.137c-.413.385-.805.794-1.172 1.224a10.42 10.42 0 0 0-.504.644 8.319 8.319 0 0 0-.651 1.064 6.234 6.234 0 0 0-.261.591 5.47 5.47 0 0 0-.353 1.606l-.007.475a5.64 5.64 0 0 0 .403 1.953 5.44 5.44 0 0 0 1.086 1.703c.338.36.723.674 1.145.932.359.22.742.401 1.14.539a6.39 6.39 0 0 0 2.692.306h.005a6.072 6.072 0 0 0 2.22-.659c.298-.158.582-.341.848-.549a5.438 5.438 0 0 0 1.71-2.274c.28-.699.417-1.446.405-2.198l-.022-.393a5.535 5.535 0 0 0-.368-1.513 6.284 6.284 0 0 0-.285-.618 8.49 8.49 0 0 0-.67-1.061 11.022 11.022 0 0 0-.354-.453 14.594 14.594 0 0 0-1.308-1.37l-.329-.28.557-.55 2.394-2.5.828-.909 1.287-1.448.837-.979 1.194-1.454.808-1.016 1.187-1.587.599-.821.85-1.271.708-1.083 1.334-2.323.763-1.524.022-.047.584-1.414a.531.531 0 0 0 .02-.056l.629-1.962.066-.286.273-1.562.053-.423.016-.259.019-.978-.005-.182-.05-.876-.062-.68-.31-1.961c-.005-.026-.01-.052-.018-.078l-.398-1.45-.137-.403-.179-.446Zm4.494 41.455a3.662 3.662 0 0 0-3.61 3.61 3.663 3.663 0 0 0 3.61 3.609 3.665 3.665 0 0 0 3.611-3.609 3.663 3.663 0 0 0-3.611-3.61Z"
|
||
fill='url(#default-radial-3094)'
|
||
/>
|
||
<path
|
||
d="M35.639 72.544l-.637.535a3.332 3.332 0 01-2.09.762H15.235a15.176 15.176 0 01-9.654-3.451c1.319.145 3.353.607 6.428-1.894l15.277-13.44a1.693 1.693 0 012.127 0l10.997 9.042 3.904-3.21c.619-.5 1.51-.5 2.128 0l12.019 9.882c1.45 1.097 3.327 2.394 7.654 3.071H58.12a3.394 3.394 0 01-1.963-.654l-.14-.108-.593-.493a1.247 1.247 0 00-.158-.159c-.672-.563-9.187-7.617-9.187-7.617a1 1 0 00-1.281.002s.021.026-9.038 7.615a1.12 1.12 0 00-.121.117zm26.262-20.96a3.678 3.678 0 00-3.61 3.609 3.68 3.68 0 003.61 3.609 3.68 3.68 0 003.61-3.609 3.678 3.678 0 00-3.61-3.609zM38.566 40.648L37.35 39.44l-.736-.762-1.858-1.999-.463-.507-2.253-2.634-.638-.791-1.974-2.569-.219-.296-1.517-2.234-.416-.673-1.087-1.866-.332-.61-.94-1.985-.178-.456-.539-1.52-.208-.718-.16-.663-.135-.72-.106-.8-.043-.511-.018-.872.004-.183.025-.522.188-1.901.059-.333.428-1.899.098-.318.318-.927.102-.24.506-1.112.351-.662.489-.806.487-.718.347-.456.4-.482.44-.484.377-.378.918-.808.671-.549c.016-.014.033-.026.05-.038l.794-.537.631-.402 1.198-.631c.018-.011.039-.02.058-.029l1.698-.705.157-.059 1.51-.442.638-.143.862-.173.572-.087.877-.109.598-.053 1.187-.063.465-.005.881.018.229.013 1.276.106 1.687.238.195.041 1.668.415.49.146.544.188.663.251.524.222.77.363.485.249.872.512.325.2 1.189.868.341.296.828.754.041.041.703.754.242.273.825 1.096.168.262.655 1.106.197.379.369.825.386.963.137.403.398 1.45a.89.89 0 01.018.078l.31 1.961.062.679.05.876.005.182-.019.978-.016.259-.053.423-.273 1.562-.066.286-.629 1.962a.626.626 0 01-.02.056l-.584 1.414-.022.047-.763 1.523-1.334 2.323-.708 1.083-.849 1.271-.599.821-1.187 1.587-.808 1.016-1.194 1.453-.837.979-1.287 1.448-.828.909-2.394 2.5-.556.55.328.28c.465.428.902.885 1.308 1.37.122.148.24.299.354.453.249.336.473.691.67 1.06.106.2.201.407.285.618.191.484.32.996.368 1.513l.022.393c.012.752-.125 1.5-.405 2.198a5.438 5.438 0 01-1.71 2.274c-.266.208-.55.391-.848.549a6.08 6.08 0 01-2.219.659h-.005a6.403 6.403 0 01-2.692-.306 5.882 5.882 0 01-1.14-.539 5.523 5.523 0 01-1.145-.932 5.458 5.458 0 01-1.086-1.703 5.662 5.662 0 01-.403-1.953l.007-.475a5.47 5.47 0 01.353-1.606c.077-.202.164-.399.261-.591.19-.37.408-.725.651-1.063.159-.221.328-.436.504-.644.367-.43.759-.839 1.172-1.224l.152-.137.244-.204z"
|
||
class="fill-navy-950 transition-colors"
|
||
/>
|
||
<path
|
||
d="M35.002 73.079l9.796-8.267a1 1 0 011.281-.002l9.938 8.269c.604.492 1.36.761 2.139.762h-25.28c.776 0 1.527-.269 2.126-.762zM41.1 43.568l.096.028c.031.015.057.036.085.055l.08.071c.198.182.39.373.575.569.13.139.257.282.379.43.155.187.3.383.432.587.057.09.11.181.16.276.043.082.082.167.116.253.06.15.105.308.119.469l-.003.302a1.726 1.726 0 01-.817 1.343 2.333 2.333 0 01-.994.327l-.373.011-.315-.028a2.398 2.398 0 01-.433-.105 2.07 2.07 0 01-.41-.192l-.246-.18a1.685 1.685 0 01-.56-.96 2.418 2.418 0 01-.029-.19l-.009-.288c.005-.078.017-.155.034-.232.043-.168.105-.331.183-.486.101-.194.216-.381.344-.559.213-.288.444-.562.691-.821.159-.168.322-.331.492-.488l.121-.109c.084-.055.085-.055.181-.083h.101zM40.481 3.42l.039-.003v33.665l-.084-.155a94.101 94.101 0 01-3.093-6.267 67.257 67.257 0 01-2.099-5.255 41.665 41.665 0 01-1.265-4.326c-.265-1.163-.469-2.343-.553-3.535a16.923 16.923 0 01-.029-1.528c.008-.444.026-.887.054-1.33.044-.696.115-1.391.217-2.081.081-.543.181-1.084.304-1.619.098-.425.212-.847.342-1.262.188-.6.413-1.186.675-1.758.096-.206.199-.411.307-.612.65-1.204 1.532-2.313 2.687-3.054a5.609 5.609 0 012.498-.88zm4.365.085l2.265.646c1.049.387 2.059.891 2.987 1.521a11.984 11.984 0 013.212 3.204c.502.748.918 1.555 1.243 2.398.471 1.247.763 2.554.866 3.882.03.348.047.697.054 1.046.008.324.006.649-.02.973-.064.725-.2 1.442-.407 2.14a17.03 17.03 0 01-.587 1.684c-.28.685-.591 1.357-.932 2.013-.754 1.457-1.623 2.852-2.553 4.201a65.451 65.451 0 01-3.683 4.806 91.02 91.02 0 01-4.417 4.896 93.66 93.66 0 002.907-5.949c.5-1.124.971-2.26 1.414-3.407.487-1.26.927-2.537 1.317-3.83.29-.969.546-1.948.757-2.938.181-.849.323-1.707.411-2.57.074-.72.101-1.444.083-2.166a30.867 30.867 0 00-.049-1.325c-.106-1.775-.376-3.545-.894-5.248a15.341 15.341 0 00-.714-1.892c-.663-1.444-1.588-2.793-2.84-3.778l-.42-.307z"
|
||
class="fill-white transition-colors"
|
||
/>
|
||
</g>
|
||
<defs>
|
||
<radialGradient id="default-radial-3094" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.593 41.714) scale(59.4764)">
|
||
<stop offset="0" stop-color="#ba7bf0" />
|
||
<stop offset=".45" stop-color="#996bec" />
|
||
<stop offset="1" stop-color="#5046e4" />
|
||
</radialGradient>
|
||
<radialGradient id="laravel-bytes-radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.593 41.714) scale(59.4764)">
|
||
<stop offset="0" stop-color="#97f6e4" />
|
||
<stop offset=".45" stop-color="#5cead4" />
|
||
<stop offset="1" stop-color="#0d9488" />
|
||
</radialGradient>
|
||
</defs>
|
||
</svg>
|
||
</a>
|
||
<a href="/blog/" class="text-violet-600">
|
||
|
||
<svg
|
||
role="img"
|
||
class=""
|
||
fill="currentColor"
|
||
fill-rule="evenodd"
|
||
viewBox="0 0 117 84"
|
||
style="pointer-events: none; width: auto; height: 36px;"
|
||
aria-labelledby="logo-title"
|
||
>
|
||
<title id="logo-title">Blog</title>
|
||
<g buffered-rendering="static">
|
||
<path
|
||
class="fill-violet-500"
|
||
d="M75.539 19.155a.387.387 0 00-.245.415l.168-.161c-.027-.152.012-.279.216-.279h.035c.083-.329.414-.609.941-.609.15 0 .337-.025.46-.093a.57.57 0 01.402-.129c.076 0 .12.008.159.019a.493.493 0 01.225.145c.066.064.106.103.167.111.055-.014.212-.053.312-.053h.402c.434 0 .793.084 1.089.346.069-.015.123-.014.176-.014.21 0 .358.08.476.193.071.068.117.163.178.231.484.35.953.714 1.214 1.225.53.403.696.83.773 1.295.041.248.051.508.092.782.176.528.183 1.057.183 1.703 0 .554-.057 1.163-.057 1.773l-.002.039c-.06.578-.237 1.212-.419 1.743-.231.894-.41 1.839-.754 2.623l-.449 1.35c-.119.454-.352.964-.528 1.418a.955.955 0 01-.142.256c-.029.038-.066.066-.085.122a.387.387 0 01-.068.12c-.179.216-.216.391-.261.65a.396.396 0 01-.032.101l-.345.72c-.29.673-.477 1.288-.979 1.905l-.269.881c-.069.198-.156.448-.283.602-.213.362-.43.764-.731 1.131v.075c0 .084-.022.15-.055.203l.001-.001-1.119 1.886a1.526 1.526 0 01-.175.399c-.042.072-.089.131-.111.193a.327.327 0 01-.022.051l-.23.444a.364.364 0 01-.075.1c-.126.122-.303.235-.401.46-.016.32-.138.59-.416.807a.372.372 0 01-.06.09c-.344.731-.831 1.316-1.106 1.953l-.004.009c-.244.529-.661.89-.968 1.243l-.375.515a1.532 1.532 0 01-.284.373c-.094.093-.197.167-.278.323a.33.33 0 01-.029.047l-1.149 1.607-.019.024c-.749.887-1.442 1.828-2.301 2.609l-.49.736a.465.465 0 01-.053.063c-.024.119-.105.522-.228 1.199-.007.188-.057.602-.057 1.017 0 .249.029.459.072.542a.407.407 0 01.032.086c.215.88.531 1.762 1.282 2.538l.023.026c.355.44.356.439.914.732l.021.012.029-.001c.52 0 1.041-.097 1.405-.248l.009-.003c.124-.048.246-.135.382-.218.173-.106.361-.21.577-.278.728-.455 1.008-.722 1.586-1.279a.363.363 0 01.103-.1.388.388 0 01.241-.058.372.372 0 01.142.036.49.49 0 01.089.028l.008-.009c.085-.224.25-.408.372-.585a.313.313 0 01.036-.044l.517-.554a.383.383 0 01.154-.101c.051-.188.166-.367.294-.496a.944.944 0 01.213-.207 4.57 4.57 0 01.324-.264s-.018.039-.033.081l.247.245a.806.806 0 00.059-.052l-.183-.518a1.36 1.36 0 00.306-.382c.114-.191.221-.395.373-.6a.192.192 0 00.013-.017c.206-.248.363-.588.559-.888a.48.48 0 01.117-.232.582.582 0 01.045-.04.756.756 0 01.157-.378c.049-.065.153-.184.153-.184l-.006.014a.388.388 0 00.137.439c.028-.045.064-.085.098-.124l-.224-.343.109-.263.26.381.021-.05-.189-.469c-.014.014-.037.045-.037.045s.062-.097.164-.184a.584.584 0 01.129-.264.557.557 0 01.291-.181l.164-.437a.4.4 0 01.094-.142l-.015.017s.136-.155.289-.213c.025-.065.071-.181.111-.258a.412.412 0 01.074-.1l.175-.42c.02-.166.089-.31.115-.361a.385.385 0 01.016-.065c.168-.485.285-.869.495-1.292.005-.089.04-.21.241-.416l1.581-3.265a.393.393 0 01.08-.11c.345-.332.632-.942.977-1.274a.377.377 0 01.105-.072 1.58 1.58 0 01.144-.218l.679-.981a.355.355 0 01.05-.059c.264-.254.325-.413.569-.705.006-.023.002-.041.002-.069 0-.062.015-.123.044-.178.096-.185.3-.419.569-.474l.131-.21.218.382.02-.033-.173-.431c.206-.199.406-.219.613-.219h.82a.522.522 0 01.215-.055c.043 0 .1.008.165.025.034.009.077.03.122.03.055 0 .11.012.159.035a1.26 1.26 0 01.663.021h.098c.118 0 .27.045.403.13.125.081.23.193.285.3l.126.301c.017.04.026.077.03.113l.003.159c.002.033.017.066.025.099.018.07.03.141.032.212v.07c0 .092-.021.21-.052.332-.025.099-.063.202-.063.277a.386.386 0 01-.118.278 1.236 1.236 0 00-.339.681c.04.013.093.036.181.078.02.01.04.022.058.035.139.1.21.093.349.093h.225c.256 0 .242.246.182.461l.006.002.143-.355a.415.415 0 00-.013-.009.515.515 0 00.147.012c.055 0 .111.003.193-.05a.389.389 0 01.209-.061c.075 0 .12.008.159.02a.444.444 0 01.194.115l.276.178a2.023 2.023 0 011.274 1.29c.034.057.061.116.086.175l.033.071a.386.386 0 01.262.366c0 .02-.009.104.054.165a.386.386 0 01.095.411c.019.093.033.188.047.282.02.139.026.281.117.391a.38.38 0 01.089.236v.196a.384.384 0 01.058.191v.171l.015.044c.009.027.009.075.058.075.154 0 .308.005.411.029a.58.58 0 01.181.074c.09.044.172.114.245.205l.11.136c.41.004.963.11 1.258.221l.219.001c.25-.055.438-.056.566-.056.19 0 .429.009.572-.037a.385.385 0 00-.265.419 2.34 2.34 0 00.249-.021c-.059-.22-.062-.453.205-.41l.305.049h.398l.095-.138a.768.768 0 01.145-.164.37.37 0 01.044-.029l.036-.07a.39.39 0 01.107-.128c.112-.087.215-.182.288-.285.043-.061.079-.121.079-.185 0-.062.015-.123.044-.178.079-.153.179-.291.258-.347.274-.379.557-.834.926-1.159.23-.423.509-.753.789-1.186a.384.384 0 01.098-.103c.435-.314.658-.731 1.023-1.05.184-.279.421-.513.718-.799a.35.35 0 01.068-.052 6.278 6.278 0 001.081-.834.366.366 0 01.075-.056c.311-.18.623-.302.932-.367.387-.18.833-.295 1.216-.295h.181c.422-.106.896-.111 1.314-.111.173 0 .345-.055.46-.055.175 0 .357.06.533.203.115.023.235.019.387.019.04 0 .08.006.118.018l.46.148h.165c.023 0 .043.002.062.006v-.006c.26 0 .52.003.78.066a.38.38 0 01.146.07c.302.233.716.418.97.709.108.103.252.225.365.354.024.027.046.055.067.083l.141-.045v.003a.302.302 0 01.121-.021h.177c.161 0 .214.098.215.224a.36.36 0 01.246.112c.129.029.259.051.391.052h.273c.028 0 .053.003.075.008v-.008c.441 0 .635.162.745.374a.393.393 0 01.038.109c.013.036.04.112.055.193.026.047.073.078.137.111a.52.52 0 01.249.14c.092.092.172.262.234.441l.008.029c.024.091.034.169.04.241.006.075-.005.138.044.232a.381.381 0 01.044.178v.61c0 .227-.009.455.085.683.03.071.037.15.022.226-.052.249-.05.449-.05.698v.443c0 .166-.014.376.072.542a.393.393 0 01.043.178v1.496c0 .166-.057.333-.057.499v.093l.078.172a.964.964 0 01.094.4v1.607c0 .166.058.277.058.443 0 .166-.058.332-.058.498v.007a.486.486 0 01.119.107c.866-.661 2.866-2.338 3.162-2.576a.396.396 0 01.095-.056c.028-.019.541-.369.927-.648.391-.283.787-.557.991-.681a.376.376 0 01.123-.067.841.841 0 00-.123.067.393.393 0 00-.117.157.747.747 0 01.24-.113l.041.261.381-.147a.505.505 0 01.307-.132h.02l.002.386c.057.056.057.111.057.111l-.058.047.001.176.01.028.258-.64c.17.164.174.335.175.366a.346.346 0 01-.169.333l.025-.009-.337.271a.484.484 0 01-.066.045l.002-.001-.272.157-.152.098a2.051 2.051 0 01-.188.162c-.133.103-.32.242-.526.394a.385.385 0 01.013.569c-.114.11-.569.825-1.31 1.595l-.587.621c-.034.034-.22.266-.254.308a.384.384 0 01-.113.155c-.387.32-1.441 1.332-1.718 1.705a.4.4 0 01-.042.049c-.078.075-.135.149-.195.197a.573.573 0 01-.227.117c-.233.154-.421.387-.613.572a.368.368 0 01-.082.06c-.263.145-.432.35-.432.604a.807.807 0 01-.067.326.709.709 0 01-.036.057c-.037.132-.07.248-.07.392v.271c0 .08-.019.144-.049.195-.195.383-.238.814-.238 1.197 0 .03-.004.06-.011.09l-.172.72a.425.425 0 01-.036.094l-.119.228.007-.012c-.094.182-.088.409-.129.633-.004.352-.064.597-.188 1.016a.4.4 0 01-.043.094c-.148.239-.192.479-.241.669a.384.384 0 01-.07.14c-.069.09-.088.197-.116.306-.026.099-.052.201-.089.304v.091a.395.395 0 01-.037.171c-.221.595-.338 1.137-.559 1.676-.116.39-.234.727-.402 1.06a6.095 6.095 0 01-.505 1.359c-.006.04-.014.08-.024.12-.009.036-.026.07-.026.106a.374.374 0 01-.021.126l-.111.322-.17.599a.4.4 0 01-.037.088l-.264.457c-.128.404-.362.809-.603 1.16-.117.237-.189.522-.37.754l-.031.034c-.001.029-.003.076-.003.117 0 .051-.01.101-.029.148-.119.286-.198.564-.396.803a2.57 2.57 0 01-.035.138c-.013.417-.241.783-.366 1.143a.364.364 0 01-.037.077 3.072 3.072 0 01-.518.625 1.33 1.33 0 01-.282.383c-.12.296-.283.473-.45.795a.364.364 0 01-.075.1 2.778 2.778 0 00-.581.822.685.685 0 01-.111.263c-.091.135-.259.276-.4.411a.392.392 0 01-.209.104c-.136.145-.275.284-.396.428-.12.141-.223.283-.266.45a.387.387 0 01-.27.275 1.38 1.38 0 01-.066.073.39.39 0 01-.113.075.39.39 0 01-.042.157c-.078.15-.223.309-.448.459-.043.039-.09.078-.137.12-.031.027-.07.051-.083.09a.385.385 0 01-.097.151c-.37.357-.684.597-1.162.781l-.009.011c-.273.383-.666.592-1.068.726-.263.143-.525.194-.735.346a.39.39 0 01-.218.073c-.015.006-.07.027-.094.034a.43.43 0 01-.05.012 6.761 6.761 0 01-1.61.34l-.036.001-.001.001-.195-.001a.31.31 0 01-.068-.01c-.455-.109-.631-.059-1.013-.161-.47-.059-.827-.171-1.241-.285a.399.399 0 01-.166-.094 1.02 1.02 0 01-.136-.164c-.131-.063-.285-.096-.404-.135a.386.386 0 01-.268-.368c0-.061-.035-.119-.068-.196l-.429-.568a.375.375 0 01-.069-.152l-.023-.014-.078-.148a.388.388 0 01-.135-.084c-.271-.261-.29-.516-.29-.777 0-.676.001-1.297.115-1.971v-.184l.363.358.002-.01-.332-.511c.158-.356.169-.665.259-.921.008-.078.028-.157.053-.238.023-.071.057-.146.057-.235 0-.043.007-.086.021-.127.029-.083.079-.178.131-.275.029-.054.072-.154.079-.168 0-.027.005-.055.011-.081.064-.246.14-.485.333-.687v-.158c0-.499.177-1 .539-1.441.014-.069.032-.131.038-.154a.475.475 0 01.019-.083c.119-.344.187-.631.352-.914.181-.633.375-1.21.848-1.789l.155-.248.218.381.006-.01-.206-.399.633-.887.025-.032c.337-.378.567-.807.996-1.236.153-.334.488-.635.783-.976a.388.388 0 01.074-.066 1.4 1.4 0 01.048-.081c.078-.151.231-.375.523-.53.151-.127.302-.166.507-.175.231-.243.51-.439.868-.56-.046-.121-.044-.198-.044-.275 0 .094.033.181.09.248l.081-.078.01.024-.024.046.012-.003.012.091a.442.442 0 00.069.034l.075.181.008.007.111-.107v-.061a.35.35 0 00.056-.013l.001-.002a.425.425 0 01-.057.014v.001l-.058.005.058-.006v-.159a.432.432 0 01-.055-.161.32.32 0 00-.175.09l.172.236a.382.382 0 01-.136-.025l-.069-.168a.197.197 0 01.027-.037l.006-.006-.196-.27.113-.378.288.386.009-.03-.245-.467c.137-.197.338-.394.538-.527a.54.54 0 01.166-.101.382.382 0 01.136-.109c.062-.03.077-.076.097-.106a.965.965 0 01.069-.09.574.574 0 01.179-.137c.016-.008.033-.014.05-.02.043-.013.06-.044.084-.07.024-.026.047-.052.069-.074.071-.113.171-.219.256-.277a.625.625 0 01.105-.059c.163-.129.293-.293.454-.489a1.06 1.06 0 01.072-.17.386.386 0 01.259-.2c.505-.112.733-.226.842-.282.206-.21.298-.395.428-.685a.698.698 0 01.16-.291.808.808 0 01.047-.041.606.606 0 01.166-.158.649.649 0 01.306-.1l-.003-.008.109-.106.029.072a.384.384 0 01.082-.123l-.005-.023.031-.015c.028-.132.08-.205.136-.312a.386.386 0 01.075-.1c.035-.034.042-.072.06-.105a.911.911 0 01.17-.228.45.45 0 01.059-.047c.259-.166.332-.383.419-.632a.338.338 0 01.022-.052c.026-.05.038-.114.064-.171a.614.614 0 01.391-.351l.269-.087a.458.458 0 01.164-.238.49.49 0 01.088-.049c.13-.105.232-.227.267-.326a.375.375 0 01.116-.169.386.386 0 01.137-.185c.07-.05.077-.119.091-.193.015-.074.027-.153.045-.237a.377.377 0 01.046-.118c.192-.325.233-.651.233-1.022 0-.575.167-1.095.345-1.666l.002-.531.171-1.811v-.902l-.009.009-.787 1.083a.31.31 0 01-.044.051c-.141.136-.336.31-.429.535a.377.377 0 01-.052.089c-.157.203-.317.404-.422.606a.386.386 0 01-.075.1c-.453.437-.678.93-1.074 1.367a.39.39 0 01-.156.104c-.363.367-.76.619-1.013 1.01a.532.532 0 01-.036.047c-.321.36-.321.362-.638.922-.126.239-.367.425-.553.665l-.097.106a.392.392 0 01-.112.212 1.687 1.687 0 01-.61.367.389.389 0 01-.089.017c-.125.08-.295.189-.376.347a.41.41 0 01-.075.1c-.52.501-.927.839-1.437 1.221-.239.269-.576.441-.805.663-.202.194-.531.336-.867.466l-.853.384a.373.373 0 01-.056.02 9.726 9.726 0 01-1.257.232h-.051l-.002.003h-.345c-.398 0-.795-.069-1.067-.195l-.225-.137c-.267-.154-.535-.256-.802-.358a.394.394 0 00.14.025s-.387-.034-.387-.387v-.007c-.033-.138-.063-.276-.169-.379l.009.008a.397.397 0 01-.064-.074l-.207-.299c-.124-.133-.156-.263-.219-.452-.473-.659-.435-1.256-.498-1.859a.536.536 0 01-.002-.04c0-.413.002-.709.063-1.063l-.001.018c.017-.109.085-.241.117-.299a.387.387 0 01.08-.173.379.379 0 01-.029-.145c0-.263.014-.371.15-.526.032-.154.041-.287.075-.441l-.05-.489a.383.383 0 01.041-.218c.089-.172.187-.383.187-.598 0-.078.024-.155.068-.22.306-.441.401-.934.452-1.376a.373.373 0 01.027-.103c.106-.256.213-.562.266-.817l.123-.588h-1.172a8.114 8.114 0 00-.328.133c-.238.106-.497.199-.717.199a.4.4 0 01-.133-.023c-.036-.002-.246-.012-.354-.031a.736.736 0 01-.257-.09c-.046-.004-.178-.017-.179-.016a.755.755 0 00-.128.07v.275l-.058 1.26c-.001.46-.231 1.036-.35 1.725a.387.387 0 01-.063.154c-.106.153-.164.352-.391.68v.209c0 .276-.071.392-.245.565l-.065.125c-.126.526-.26.733-.494.967l-.001.005c0 .21-.04.402-.196.534-.229.484-.508.964-.786 1.394a.562.562 0 01-.027.036s-.427.515-.426.512c-.084.166-.243.305-.421.474l-.026.051a.378.378 0 01-.237.199c-.319.145-.588.422-.818.778a.386.386 0 01-.116.115c-.549.353-1.101.701-1.711.877a.25.25 0 01-.026.007c-.253.054-.386.143-.504.213a1.317 1.317 0 01-.374.165c-.16.07-.378.129-.526.129a.993.993 0 01-.291-.06l-.655-.106c-.322-.001-.811-.014-1.129-.13l-.962-.273a.475.475 0 01-.063-.023c-.151-.073-.294-.091-.445-.237-.013-.012-.025-.026-.037-.04-.063-.082-.156-.123-.221-.161a.97.97 0 01-.174-.128.526.526 0 01-.08-.101c-.27-.242-.539-.634-.756-.9-.381-.312-.753-.744-.945-1.229a.76.76 0 01-.059-.25c-.007-.077.008-.181-.045-.283l-.008-.016c-.223-.483-.294-1.117-.449-1.713-.163.247-.312.446-.395.647a.443.443 0 01-.039.071c-.075.108-.12.268-.179.371a.712.712 0 01-.11.146 1.883 1.883 0 01-.156.256c-.051.073-.109.127-.132.213a.388.388 0 01-.076.15l-.225.27a.484.484 0 01-.054.056l.009-.007c-.097.091-.138.122-.171.251a.387.387 0 01-.106.181c-.054.052-.112.143-.235.242-.081.199-.219.453-.435.632-.17.241-.423.445-.577.743a.336.336 0 01-.032.051c-.745 1.018-2.495 2.319-4.048 2.319-.311 0-.623-.055-.932-.166h-.103c-.336 0-.727.105-.96.11a.383.383 0 01-.117.106.439.439 0 01-.246.061.562.562 0 01-.385-.117c-.091-.048-.168-.102-.241-.152-.039-.027-.069-.064-.121-.064a.807.807 0 01-.29-.068 3.682 3.682 0 01-.494-.27l-.01-.007c-.247-.17-.494-.3-.69-.45a1.478 1.478 0 01-.35-.362c-.492-.292-.904-.508-1.154-.991a.369.369 0 01-.031-.08c-.008-.032-.014-.062-.032-.084-.02-.025-.058-.015-.111-.015h-.058s-.134.021-.269-.109a9.169 9.169 0 00-.055-.053l.267.107-.305-.149-.345-.444a.294.294 0 01-.031-.047c-.347-.613-.79-1.127-.94-1.68l-.058-.074a1.018 1.018 0 01-.302-.195c-.244-.228-.539-.77-.639-2.39l-.002-.002a.387.387 0 01-.122-.282v-.85a.384.384 0 01-.057-.202v-3.38a.39.39 0 01.012-.097c.05-.192.045-.432.045-.624v-.323l.387.377-.168-.734c-.064.031-.105.132-.105.132l.001-.061s0-1.1.001-1.097a1.814 1.814 0 01-.116-.565c0 .213.173.386.387.386l-.363-.52.112-.325.037.051v-.196l.048.048a.382.382 0 00-.048.147v.002l.239.335.076-.221-.267-.263.002-.003-.05-.051c0-.471.232-.886.354-1.416.004-.014.007-.027.012-.04.049-.142.055-.344.073-.558.024-.274.06-.561.15-.812.17-.839.193-1.724.578-2.458.02-.134.015-.266.026-.381a.982.982 0 01.087-.336 9.98 9.98 0 01.288-1.201l.008-.024s.268-.724.268-.721a.37.37 0 01.115-.242.51.51 0 01.017-.231.494.494 0 01.154-.225.385.385 0 00-.099.397.44.44 0 01.236-.061l-.018-.047-.122-.122v-.053l.086.086-.001-.002-.085-.085c0-.37.171-.745.361-1.17.123-.581.309-1.16.61-1.683l.006-.009v-.072l.03.03.001-.002-.031-.031c0-.135.036-.272.092-.413.044-.109.106-.223.139-.352.01-.303.121-.605.244-.851a.645.645 0 01.048-.135 3.08 3.08 0 01.116-.201.29.29 0 01.015-.058c.108-.312.331-.62.385-.983a.34.34 0 01.007-.034c.183-.767.603-1.421 1.088-2.01l.005-.008a.467.467 0 01-.069-.219c0-.116.065-.256.17-.377l.375-.931a.378.378 0 01.033-.063c.452-.707.734-1.415 1.125-2.116.232-.553.575-1.052.805-1.55a.342.342 0 01.033-.059c.086-.125.13-.208.173-.375a.386.386 0 00.234.457c.021-.038.04-.074.058-.114l-.257-.432.126-.241v-.067l.023.022.001-.002-.024-.025c0-.236.067-.477.311-.791a.365.365 0 01.096-.088c.052-.034.131-.093.168-.121v-.02c.002-.031.005-.202.175-.366a.385.385 0 01.13-.083c.08-.031.102-.115.14-.187.035-.065.069-.131.105-.194a.382.382 0 01.065-.182.493.493 0 01.323-.182l.021-.001v.097l.002.001v-.098c.023 0 .053.005.085.013l-.083-.137.287-.554a.41.41 0 01.075-.1c.163-.157.331-.162.362-.163l.019-.001.001.173a.064.064 0 00.016-.006l.103-.12-.058-.091-.011-.024a.386.386 0 01.07-.417l.46-.499.155-.147a.39.39 0 01-.027-.119l-.001-.018a.56.56 0 00.031.135l-.003.002.011.024-.008-.026.041-.039s-.014.04-.014.063a.2.2 0 00.006.045.38.38 0 00.277.172.362.362 0 00.036-.042l-.126-.559-.041-.091.016-.02-.004-.021.036-.018.132-.159c.065-.181.138-.337.302-.432a.683.683 0 01.3-.089c.046-.025.083-.066.126-.098a1.04 1.04 0 01.281-.158l.019-.006-.019.006zm19.948 62.116c.013.038.03.068.038.076.135.137.274.114.274.114l-.312-.19zm11.321-11.552l-.022.041-.237-.382-.109.21.264.441-.034.113a.385.385 0 01-.26-.481l-.333 1.122-.269.476a.524.524 0 00-.275.445c-.059.179-.207.355-.346.578l.302.544-.006.015-.354-.347v.192l-.083.2.275.419a.771.771 0 01-.063.094.385.385 0 01-.244-.359c0 .072-.067.151-.161.223a.575.575 0 00-.229.233c-.032.057-.048.127-.084.197a.381.381 0 00-.044.178c0 .067-.042.099-.111.165a.384.384 0 00-.101.164l-.173.554.044.058-.013.013-.037-.047-.03.116c-.316.339-.544.798-.676 1.23-.016.008-.032.016-.047.026-.243.156-.403.323-.45.59l-.121.116-.649.57-.747.776a.393.393 0 00-.05.064c-.163.262-.441.415-.659.677l.073-.034c-.052.038-.1.079-.131.108l-.773.402c-.305.196-.61.346-.915.493h-.043l-.003-.003c-.109-.106-.135-.282-.169-.431v-.172c.085-.28.096-.552.137-.716.192-.281.208-.558.208-.84v-.111c0-.231.105-.507.201-.738l.013-.039c.221-.746.61-1.544 1.108-2.343a.377.377 0 00.035-.073l.402-1.108a.344.344 0 00.022-.101c.023-.027.145-.171.228-.251l-.268.108.386-.384v.017c-.001.012.007.084-.06.148a.385.385 0 00.108-.191c.045-.193.15-.351.272-.506.159-.201.346-.396.519-.618a.361.361 0 00.059-.109l.069-.075.441-.638a.836.836 0 00.138-.196c.019-.034.026-.071.061-.105a.325.325 0 00.035-.039l1.094-1.387c.134-.171.217-.309.346-.399a.455.455 0 00.084-.065l.28-.27a.388.388 0 00.09-.131c.103-.248.26-.397.415-.639l.321-.36a.386.386 0 00.055-.079c.039-.077.075-.156.155-.232l.024-.026c.294-.34.471-.623.765-1.02a.382.382 0 00.071-.167.695.695 0 01.074-.047.391.391 0 00.1-.07l.83-.801c.268-.311.479-.626.748-.833l.181-.17a9.987 9.987 0 01-.314.879.394.394 0 00-.029.148c0 .062-.035.121-.063.188-.055.128-.114.264-.15.412a1.461 1.461 0 00-.075.481l-.038.294c-.203.227-.249.403-.249.564 0 .038-.003.094-.004.117a.415.415 0 00-.043.051 1.28 1.28 0 00-.241.774.747.747 0 01-.043.226l-.033.029a.503.503 0 00-.154.355v.015c-.196.26-.268.462-.337.793a.413.413 0 00-.008.078c0 .061-.012.125-.054.165l.181.448zm-8.372 10.175l-.003-.009a.4.4 0 00.253-.215.377.377 0 01-.25.224zm.278-.345l-.008.056a.4.4 0 00.009-.084l-.001.028zm1.896-.525l-.033.03s.015-.016.033-.03zm5.449-.39l-.06.063c.07.066.164.104.264.104l-.014-.022a.39.39 0 01-.19-.145zm-1.673-3.507l-.231-.314.024.059.204.259.003-.004zm6.571-5.192l-.028.097c.034.01.07.015.106.015l-.078-.112zm.253.07zm.192-.224a.413.413 0 010 0zm-3.931-1.655a.108.108 0 01.057-.017c.022-.066.045-.132.064-.197a.366.366 0 00-.103-.023h-.017l-.001.237zM49.432 19.629c.407-.259.679-.277 1.293-.277l.172.002v-.002c.109 0 .22.018.292-.017a.38.38 0 01.168-.039c.059 0 .126-.024.199-.043a1.74 1.74 0 01.434-.068c.1 0 .196.039.268.109a.396.396 0 00.169.111c.045-.013.141-.038.206-.048l-.034.003c.546-.117.972-.285 1.518-.285.04 0 .08.006.118.018.134.043.266.092.399.092.074 0 .147.022.209.062.093.06.158.049.251.049.062 0 .158.011.251-.049a.386.386 0 01.358-.032c.021.002.093.01.131.017a.64.64 0 01.266.114c.036.009.068.006.087.006v.003l.029-.003h.17c.354-.057.71-.111 1.123-.111.143 0 .318.003.481.027a.392.392 0 01.324-.138.49.49 0 01.426.241.957.957 0 01.206-.019c.169 0 .331.029.443.087l2.328.82c.206.068.364.183.557.416a.687.687 0 01.283.231c.075.009.248.048.337.199.142.12.265.28.415.515l.446.286-.03.101a1.04 1.04 0 01-.042.363l.043.056.228-.356c.104.226.318.314.507.434.189.121.368.255.506.44.104.067.186.122.24.177.076.078.124.16.147.252.118.061.214.15.296.255.103.132.166.31.291.431.062.06.102.138.115.224l.172 1.219a.327.327 0 01.004.054v.72l-.055.594.048.275a.393.393 0 01.005.107v-.001c-.061.713-.251 1.602-.559 2.195l-.747 1.441a.41.41 0 01-.075.1l-.415.399-.545 1.052a.429.429 0 01-.057.082c-.405.446-.759.996-1.267 1.393a.579.579 0 01-.18.148.628.628 0 01-.122.045l.001.014a.347.347 0 01-.035.187.862.862 0 01-.197.282c-.35.336-.758.785-1.282 1.234l-.004.003-.849.709c-.103.097-.224.178-.342.264-.096.07-.197.141-.238.281a.387.387 0 01-.263.261c-.29.084-.489.258-.667.399a2.22 2.22 0 01-.409.269 1.42 1.42 0 01-.157.145c-.057.044-.121.078-.167.144a.386.386 0 01-.227.156c-.016.004-.024.02-.036.032-.035.034-.068.073-.102.112-.077.089-.159.18-.251.253a1.573 1.573 0 01-.618.426.395.395 0 01-.057.014c-.265.042-.479.225-.656.395l-.032.028c-.312.241-.566.476-.816.596l-.028.013c-.234.09-.374.18-.561.36l-.056.055a.393.393 0 01-.163.097c-.129.05-.256.064-.385.067a.842.842 0 01-.137.18 1.9 1.9 0 01-.559.356c-.069.022-.142.111-.223.176a1.44 1.44 0 01-.252.169c-.235.213-.481.338-.793.338l-.012.001c-.219.126-.436.259-.61.469a.382.382 0 01-.18.121c-.15.049-.274.137-.412.21-.2.105-.419.19-.705.196-.39.342-.827.563-1.314.823-.404.324-.86.495-1.262.772a.425.425 0 01-.046.027l-.858.431.57.001.593.055h1.936l.045.002 1.437.167c.025.003.05.008.074.016.083.026.178.073.279.121.075.035.153.082.235.082l.666.057a.377.377 0 01.119.029c.487.209.975.22 1.361.36.32.024.641.189.897.312a.388.388 0 01.162.148l.092.147c.013 0 .026.001.038.003v-.003c.466 0 .816.222 1.152.476.137.039.222.078.342.078.101 0 .197.038.269.108a.516.516 0 01.077.099l.107.051c.074.036.118.08.141.129l.004-.009c.266.357.533.471.799.757l.228.132a.35.35 0 01.08.061l.001-.001c.094.09.165.191.229.296.053.088.095.182.173.258a.374.374 0 01.057.069c.04.029.241.181.338.322.02.028.035.059.046.091.036.037.093.099.118.139a.516.516 0 01.059.134c.14.095.235.236.318.393.133.221.324.442.467.651.124.182.215.362.254.528.133.312.359.741.359 1.165v.111c0 .256-.001.513.052.82l.058.388a.402.402 0 01-.006.153l.001-.001-.047.231-.005.077-.053.326c0 .061.04.149.072.21a.392.392 0 01.042.148l.001.084a.37.37 0 01-.055.203c-.12.241-.185.533-.264.793a2.42 2.42 0 01-.222.538 2.71 2.71 0 01-.324.755c-.112.19-.232.365-.311.568a.387.387 0 01-.167.194c-.168.098-.245.187-.279.317a.39.39 0 01-.163.226 1.04 1.04 0 01-.37.323l-.11.195c-.016.028-.035.054-.035.1 0 .11-.047.215-.128.289l-.805.72a.297.297 0 01-.035.027c-.873.617-1.629 1.177-2.502 1.682a.386.386 0 01-.185.051 1.304 1.304 0 01-.093.034.5.5 0 01-.145.022l-.035-.001a.811.811 0 01-.153.123c-.065.042-.158.084-.234.158a.388.388 0 01-.268.108h-.003a.374.374 0 01-.081.106c-.048.046-.127.115-.319.115h-.15l-.38.163-.005.005a.404.404 0 01-.132.087c-.631.325-1.368.547-1.995.821a.368.368 0 01-.118.031.772.772 0 01-.22.106c.024-.004.047-.01.047-.01s-.158.063-.249.071l-.075.001a.388.388 0 01-.195-.053c-.066.011-.124.067-.169.111-.104.1-.3.163-.613.163h-.043a.635.635 0 01-.148.149.725.725 0 01-.442.128h-.25a3.414 3.414 0 01-.641.211c-.198.049-.403.096-.608.194a.39.39 0 01-.146.038l-.482.001c-.171 0-.297-.003-.449-.038-.056.045-.178.144-.262.198a.386.386 0 01-.209.061h-.016a.383.383 0 01-.146-.036l-.337-.074c-.317.008-.679.111-.992.161a.375.375 0 01-.179-.014c-.112-.036-.187-.082-.261-.091l-.07.025a.383.383 0 01-.241.085s-.085-.008-.175-.053c-.183.06-.321.108-.515.108a2.94 2.94 0 01-.689-.111h-.116c-.215 0-.481.049-.703.055l-.044.001a.386.386 0 00.386-.387l-.001-.029c-.1.011-.201.022-.296.027l-.089.389s-.154-.014-.284-.108a.537.537 0 01-.148-.164.219.219 0 00-.033.012.385.385 0 01-.399-.039l-.056.022-.145-.057a.385.385 0 01-.341-.277 2.204 2.204 0 01-.51-.06.435.435 0 01-.333-.271.379.379 0 01-.034-.139l-.001-.08.387.385-.387-.386c0-.144.037-.228.085-.302.003-.006.008-.011.012-.017a1.16 1.16 0 01-.286-.126h-.459c-.167 0-.342-.126-.374-.155l-.009-.008.268.108-.387-.389.001-.022a.48.48 0 01.178-.332c-.031-.117-.015-.264.125-.414.096-.101.34-.27.52-.359a.793.793 0 01.31-.089h.518c.11 0 .186.002.27.024l.001-.001c.477-.172 1.072-.178 1.668-.293a.387.387 0 00-.312.417l.003.023c.068-.009.137-.018.206-.03-.072-.202-.085-.417.177-.417h.046a.913.913 0 00.071-.033c.053-.029.107-.063.16-.094a.987.987 0 01.438-.149.97.97 0 01.434-.111c.044 0 .088-.022.121-.031a.695.695 0 01.166-.025c.059 0 .127.022.18.044.071-.054.152-.099.223-.099.063 0 .128.012.203.043.034.014.077.04.15.068h.285c.186-.047.516-.101.804-.239a.369.369 0 01.102-.033c.021-.008.052-.019.086-.029l.007-.006a.421.421 0 01.188-.076c.399-.115.411-.106.579-.309a.387.387 0 01.13-.101c.254-.123.57-.133.825-.194a.387.387 0 00-.294.421l.003.018c.076-.012.153-.022.226-.034-.061-.202-.065-.416.185-.416h.203c.073-.026.126-.075.194-.12a1.76 1.76 0 01.386-.197c.541-.156 1.085-.198 1.517-.459a.387.387 0 00-.149.497l.099-.039a.383.383 0 01.027-.313c0-.114.056-.2.224-.2l.089.001c.187-.02.354-.066.51-.128a.35.35 0 01-.182-.32v-.105l.179.177a.371.371 0 01.001-.141.67.67 0 01-.013-.071l-.098-.188a.8.8 0 01.301-.25c.152-.076.362-.129.559-.198a3.451 3.451 0 011.147-.634c.546-.323.937-.697 1.436-1.018a.342.342 0 01.042-.023c.045-.022.127-.049.178-.064a.279.279 0 01.064-.068l-.053-.133.109-.105.073.177a.349.349 0 00-.129.061l.158.397c.033-.019.055-.044.055-.083 0 0 .044 0 .055-.037l-.017-.04c-.016-.021-.038-.055-.038-.089l.001-.002-.085-.207a.355.355 0 01.147-.007l.014.141.038-.036a.8.8 0 00.07-.019c-.021-.043-.06-.074-.122-.086l-.029-.273c.182-.039.301-.183.438-.329.192-.206.394-.432.66-.611.051-.275.175-.43.227-.582a.392.392 0 01.139-.187c.167-.12.246-.243.33-.444a.346.346 0 01.052-.089c.12-.155.165-.275.206-.423v-.272l.375.366.001-.007-.322-.566c.188-.318.343-.632.348-.95l-.057-.626c0-.104-.077-.227-.14-.299l-.666-.367h-.188a.392.392 0 01-.197-.054c-.683-.405-1.42-.5-2.103-.5l-.03-.001c-.681-.055-1.474-.221-2.154-.221l-.209-.043a1.865 1.865 0 01-.424.043c-.159 0-.358-.004-.536-.036a1.9 1.9 0 01-.122.033.385.385 0 01-.204.059l-1.032-.001a.85.85 0 01-.405.112.385.385 0 01-.139-.026l-.507-.196c-.067.005-.112.048-.166.073a.924.924 0 01-.396.093c-.105 0-.285-.057-.464-.14-.098.03-.224.052-.254.057a.366.366 0 01-.122.027l-1.938.11c-.448.054-.895.106-1.241.111a3.309 3.309 0 01-1.04.168s-.546 0-.541-.001a2.202 2.202 0 01-.296.02c-.07.002-.127-.012-.188.063a.39.39 0 01-.276.139h-.155a.392.392 0 01-.239-.098c-.061.017-.121.048-.179.07a1.25 1.25 0 01-.277.076c-.31.116-.673.222-.982.229h-.084a.634.634 0 01-.29.056s-.046.004-.122-.02l-.051-.016-1.233.395c-.388.186-.718.306-1.239.306h-.248l-.766.158a.395.395 0 01-.181-.006 3.662 3.662 0 00-.79-.149c-.375 1.134-.744 2.222-.907 3.359l-.002.015a.738.738 0 01-.23.393c-.125.121-.214.206-.331.41l.047.483v.263a.355.355 0 01-.136.292l.018-.008a.083.083 0 00.012-.015l-.024.079a1.055 1.055 0 01-.056.159.544.544 0 01-.216.254v.132c0 .118-.022.236-.051.359-.027.111-.064.228-.064.361v.162c0 .066-.013.12-.032.159a.98.98 0 01-.185.329 1.732 1.732 0 01-.098.107.386.386 0 01-.06.542c-.109.088-.139.22-.18.361-.06.204-.117.429-.225.658l.019.073c.056.218-.072.346-.193.416l.088-.035c-.131.126-.218.212-.226.36.034.253.016.407-.038.513a.558.558 0 01-.323.273 1.483 1.483 0 01-.215.059v.012c0 .166-.057.277-.057.444v.221a.692.692 0 01-.173.461v.141a.375.375 0 01-.045.187l.002-.001c-.074.142-.072.214-.072.32v.271a.397.397 0 01-.018.125l.001-.002c-.078.259-.385.647-.647.961a.384.384 0 01-.236.135.555.555 0 01.038.173.41.41 0 01-.222.373.715.715 0 01-.251.066l-.086.002a.386.386 0 01-.351-.224l-.01.048c-.004.159-.027.26-.085.348l-.04.193a.68.68 0 01.068.246.388.388 0 01-.118.278 1.727 1.727 0 01-.123.219.387.387 0 01-.704-.193l-.057-.831c.006.098.05.186.116.25a.417.417 0 01.037-.155l-.151-.172.054-.418v-.239c-.11.084-.246.096-.246.096s-.257-.004-.38-.198l-.127-.092a.384.384 0 01-.167-.318c0-.13.011-.31.058-.458v-.595c0-.061.015-.123.043-.178a.813.813 0 00.071-.292l-.049-.285.361.296v-.003l-.369-.369c0-.08-.059-.156-.077-.203a.53.53 0 01-.038-.184.38.38 0 01.058-.203v-.795c0-.033.004-.065.012-.097.034-.132.055-.246.089-.328a.793.793 0 01.089-.161.509.509 0 01-.075-.245c0-.071.019-.14.055-.199a.809.809 0 00.002-.052l-.053-.357.382.33-.386-.387c0-.066.063-.277.063-.277s-.006.04-.006.056c0 .202.156.368.353.385l-.008-.061-.318-.465.126-.326a2.507 2.507 0 01-.062-.151.369.369 0 01-.033-.161v-.105l.386.384-.365-.513c.111-.322.108-.698.164-.913a.388.388 0 00.315.479l.01-.077-.034-.055a.388.388 0 01-.246-.361c0-.039-.022-.077-.03-.106a.614.614 0 01-.028-.171l.002-.04c.059-.567.234-1.078.351-1.645a.389.389 0 00.292.455l.02-.084-.102-.146a.383.383 0 01-.145-.205l-.05-.072.054-.157.211-.659v-.209l.36.352-.36-.36c0-.268.067-.535.136-.736a.338.338 0 01.022-.052c.334-.644.44-1.397.662-2.148a.39.39 0 01.096-.161l-.05-.337.383.33-.344-.565c.163-.313.38-.728.544-1.196l.103-.546v-.071l.343.34.002-.015-.324-.455c.225-.648.449-1.085.673-1.773a.446.446 0 01.015-.073l-.009-.047.02.016.024-.048-.054-.054c0-.66.231-1.148.479-1.626.047-.211.096-.345.096-.479a.37.37 0 01.013-.1l.46-1.718a.541.541 0 01.014-.043l.286-.715c.334-.914.724-1.986.952-3.004.001-.447.024-.772.287-1.163.092-.171.23-.376.23-.627 0-.032.004-.065.012-.097.121-.465.304-.984.541-1.349.022-.078.022-.131.022-.16v-.388l.386.386-.386-.386c0-.229.072-.455.207-.63.097-.408.149-.852.201-1.154a.327.327 0 01.021-.074l.862-2.216a.381.381 0 01.17-.196.676.676 0 01.139-.254.384.384 0 01-.048-.186c0-.086.026-.19.088-.28-.253.121-.478.289-.793.433-.396.414-.737.537-1.081.813l-.016.012c-.102.074-.224.14-.347.21-.111.063-.229.124-.298.235a.394.394 0 01-.135.131c-.137.079-.288.158-.419.244-.075.049-.147.092-.179.153a.386.386 0 01-.343.209.251.251 0 00-.218.149.382.382 0 01-.148.177c-.178.115-.3.268-.425.4a1.914 1.914 0 01-.361.31 14.26 14.26 0 00-1.711 1.797c-.034.126-.082.259-.126.392-.037.111-.074.221-.074.322a.443.443 0 01-.079.251.616.616 0 01-.066.08c-.018.019-.053.035-.071.069a.382.382 0 01-.051.075l-.312.358.001-.001a1.45 1.45 0 01-.31.21.618.618 0 01-.226.064l-.02.001s-.069.009-.173-.041l-.218-.105h.001a.366.366 0 01-.086-.054.373.373 0 01-.141.033h-.102a.388.388 0 01-.328-.238 1.25 1.25 0 00-.107-.214c-.015-.023-.026-.046-.043-.058a.382.382 0 01-.216-.158l-.109-.158.315.162-.357-.239a.568.568 0 00-.313-.323c-.284-.047-.464-.306-.464-.6a.38.38 0 01.058-.203v-.241l.118.119-.118-.119c0-.198-.135-.305-.375-.437a.383.383 0 01-.195-.275v-.001l-.12-.122v-.157l.063.062v-.003l-.006-.064.006.068.29.286.022.004-.256-.637.009-.008a.609.609 0 01.209-.114.404.404 0 01.333.07h.105l.207-.9.111-.906a.44.44 0 01.082-.225c.042-.059.146-.128.208-.188.032-.031.065-.06.097-.121a.396.396 0 01.075-.101c.375-.361.607-.719.865-.951a.386.386 0 01.263-.302c.195-.063.338-.221.485-.383.203-.225.403-.468.64-.647.029-.036.034-.086.058-.133.05-.096.114-.197.219-.299a.391.391 0 01.1-.07c.061-.029.101-.078.158-.11a.68.68 0 01.351-.094.842.842 0 01.113-.097c.024-.016.056-.028.081-.057.171-.31.42-.468.669-.548.138-.044.249-.071.342-.101a.283.283 0 00.161-.101.72.72 0 01.037-.041c.238-.229.583-.411.938-.583.326-.399.808-.695 1.296-.876l1.459-.811-.009.005c.334-.213.818-.334 1.222-.488.335-.431.869-.64 1.528-.817l.295-.189.113.387.096-.062v-.386c-.008 0-.022.003-.022.003s.109-.074.165-.116a1.13 1.13 0 01.381-.204l.011-.004c.357-.12.772-.39 1.185-.45l.009-.001-.005.001.298-.005c.137-.317.516-.388.795-.388h.275c.294-.383.69-.429 1.167-.495a.453.453 0 01.052-.003c.052 0 .108-.006.143-.055a.394.394 0 01.049-.059c.3-.289.68-.496 1.131-.496.042 0 .083.007.122.02l.089.029c.054-.042.09-.102.139-.148a.758.758 0 01.57-.233h.189l.055-.054.022.054h.004c.11 0 .171.045.2.114l-.026-.274c.094-.018.182-.025.265-.037.06-.007.114-.015.155-.093a.386.386 0 01.253-.198c.114-.028.241-.036.374-.042.117-.005.244-.004.37-.049.377-.178.932-.301 1.427-.36a.386.386 0 00-.336.441l.205-.034c-.07-.201-.079-.41.181-.41h.2c.229-.032.407-.133.587-.204.181-.072.363-.125.573-.129.49-.058.88-.262 1.418-.324a.386.386 0 01.522-.119h.064c.064 0 .111.016.143.043.038-.03.092-.07.141-.098zm-22.688 46.8l-.002-.004-.006.004.003.003.005-.003zm76.012-.315l.003-.003-.006-.007.003.01zm-76.479-.799a.25.25 0 01-.023.031l.219.219.01-.043a.369.369 0 01-.206-.207zm.055-.255v.053a.39.39 0 01-.019.124l.151.15-.132-.327zm-.038-.536a.298.298 0 00-.045.109c.003.09.038.172.092.236l-.008.091.231.199.003-.013-.066-.165a.385.385 0 01-.16-.112l.012-.122a.424.424 0 01-.043-.126l-.016-.097zm86.356.458l-.007.02.059.058-.052-.078zm-86.05-.048a.43.43 0 01-.146-.07l-.091-.225-.01.108a.345.345 0 00.101.117l.047.117a.397.397 0 00.099.022l.006-.028-.006-.041zm13.47.011a.398.398 0 00.074-.026c.021-.009.034-.017.034-.017l-.108.043zm-.407-.038a.458.458 0 00.1.038l-.109-.043.009.005zm-12.586-.263l-.013.059.153.118.047.012-.003-.005-.184-.184zm-.562-.132l.003.009.117.096-.12-.105zm22.164-.517a.287.287 0 01-.119.139c-.053.206-.193.427-.193.427a.387.387 0 00.378-.302.893.893 0 01-.2-.068l.167.038V64a.26.26 0 00-.021-.036l-.012.031zm-.813.255c-.066.027-.133.05-.201.071.058.144.199.24.358.24 0 0-.093-.146-.157-.311zm-21.48.162l.018.015-.008-.018-.007-.007-.003.01zm12.556-.333a1.322 1.322 0 01-.09-.242 1.009 1.009 0 01-.174-.028.385.385 0 00.376.475l-.028-.045-.03-.009c-.057 0-.057-.055-.057-.055v-.055c0-.016.001-.029.003-.041zm9.77-.181V64a.394.394 0 01.032.089l-.032.14.011-.001a.178.178 0 00.028-.003.407.407 0 00-.007-.136l.05-.216-.083-.03.001.055zm1.772-.01a.152.152 0 00.048-.029l.018-.017s-.026.02-.066.046zm-11.31-.054l.053.053h.002l-.053-.053h-.002zm.1-.022l-.01.003.02.02v-.026l-.01.003zm-13.109-.094l-.003.012h.013l-.008-.02-.002.008zm13.083-.315c-.012.017-.027.038-.032.05l-.001.002.012.056h-.029a.79.79 0 00-.013.063l.002.025.003.014a.265.265 0 00-.048.082l.015.014a.38.38 0 00.127.021l-.003-.009a.122.122 0 01-.05-.03.148.148 0 01-.041-.078.164.164 0 01.021-.025c.007-.007.017-.014.028-.022l-.012-.055h.064l-.043-.108zm.036.138a.325.325 0 00-.045.025c.018.075.035.133.042.155l.003.001v-.181zm-13.051-.253l.115.276.171-.171c-.004-.02-.026-.046-.053-.074l-.064-.062c-.03-.03-.054-.059-.054-.079l-.115.11zm12.974.12c-.07.047-.124.047-.211.047-.025 0-.053 0-.083-.002a.41.41 0 00.032.077.308.308 0 01.114-.019h.139a.346.346 0 01.017-.056.926.926 0 01-.008-.047zm-10.511.064l-.009.019.018.018-.009-.037zm80.326-.3l-.115.115-.121-.299.064-.032.057-.055s0 .055.058.055c.057.055.057.111.057.166v.05zm-71.112.004l-.005-.005.002.003.002.002h.001zm14.48-.466l-.004.002.121.298-.067-.326-.05.026zm.474-.239c.065.167.16.317.16.317a.386.386 0 01-.355-.234l.195-.083zm-13.425-.054a.204.204 0 00.017-.015l.05-.017.002-.011a.42.42 0 00-.009-.22l-.06.263zm-10.521-.074a.385.385 0 00.264-.147h-.001a.473.473 0 01-.262.142l-.001.005zm24.942-.312l-.048.03a.492.492 0 01-.009.076.384.384 0 00.256.097l-.143-.237-.056.034zm.785-.334l-.068.04a.368.368 0 00-.145.031c-.021.076-.049.15-.075.211l.08-.048a.384.384 0 00.002-.001l.019-.012-.029.057a.498.498 0 01-.048.112l.176-.072c.109-.105.097-.206.095-.258a.548.548 0 00-.007-.06zm-25.741.181l-.027.025v.056a.586.586 0 01.043.1l-.016-.181zm25.489.165l-.008.013.018-.031-.01.018zm43.348-.543c-.1.161-.275.291-.275.291.17 0 .319-.111.369-.271l-.094-.02zm15.796.15a2.507 2.507 0 00-.023.125.353.353 0 00.108.016l-.085-.141zm-70.552.001c-.019-.091-.016-.174.028-.23a.38.38 0 00-.222-.07h-.01c.175.007.208.139.186.292l.018.008zm64.314-.246c.024-.001.037-.011.045-.031a.364.364 0 01-.045-.043v.074zm-.034-.006l-.134-.337a.327.327 0 00-.076.062.723.723 0 00-.083.164.387.387 0 00.027.101c.043-.027.1-.04.184-.04.03.029.06.043.082.05zm-64.488-.015s-.018-.013-.045-.023l.045.023zm53.975-.262a.38.38 0 01-.32.17s.209-.018.32-.17zm10.62.1a.383.383 0 01-.058-.204h-.014l-.001.08.058.139.015-.015zm-77.614-.44l-.014.015.007.017.046.035-.039-.067zm66.569-.266a.961.961 0 01-.183.112.38.38 0 00.204-.059.583.583 0 00-.021-.053zm-26.457-.432l.004-.002-.004-.001v.003zm19.387-.266l-.025.011.01.053.118.191-.103-.255zm-63.448-.334l.009.014c.04.014.083.021.127.021 0 0-.062-.005-.136-.035zm.239.012l-.004.01a.364.364 0 01-.099.013s.045-.004.103-.023zm-.428-.155a.302.302 0 00.05.062l.001-.003a.323.323 0 01-.051-.059zm83.581-.321l-.158-.159-.004.03a.39.39 0 00.015.136.403.403 0 00.026.032l.121-.039zm-19.759-8.066l-.354-.346v.191a2.83 2.83 0 00-.108.446 4.649 4.649 0 01-.059.252.386.386 0 00-.063.211c0 .43-.185.857-.261 1.169-.164.235-.258.491-.341.724-.051.142-.075.279-.167.35a.385.385 0 00-.096.109l-.916 1.545-.263.405-.722.749a.364.364 0 00-.04.048 8.016 8.016 0 01-.921 1.098c-.381.137-.582.4-.874.629-.071.039-.15.03-.231.049a1.111 1.111 0 00-.382.161h-.002c-.104-.195-.282-.497-.335-.806v-.241a.384.384 0 00-.164-.321l-.008-.182c0-.128-.008-.3.036-.428a.387.387 0 00.021-.126v-1.128a.778.778 0 00.173-.479.522.522 0 00-.026-.13c.053-.114.088-.226.118-.331.022-.077.032-.148.065-.2a.363.363 0 00.073-.228v-.087c.046-.424.134-.556.313-.772l-.009.004a.355.355 0 00.098-.257v-.279a.347.347 0 00.115-.272v-.108c0-.054.042-.084.067-.125.056-.09.108-.186.142-.302l.103-.248a1.1 1.1 0 00.091-.322.833.833 0 00-.026-.141c.256-.365.465-.741.628-1.205a.377.377 0 00.03-.154v-.083l.369-.864.216-.467a.332.332 0 00.043-.128l1.037-1.683.246-.379.108-.078.013.01.169.239-.264-.103.164.157a.418.418 0 00.114.08l.007.1c.075.43.317.843.608 1.022.142.148.254.325.374.475.125.156.259.289.413.378.195.113.307.344.346.457.033.096.077.207.093.249v.693c-.099.227-.115.518-.115.649l.354.354zm-58.974 7.654l.134.136-.134-.136zm43.873-.079a1.126 1.126 0 01-.023.104l.061-.024c.03-.047.067-.09.106-.133a.42.42 0 00-.06-.03l-.084.083zm8.681-.187l-.003-.008a.41.41 0 00.252-.203.383.383 0 01-.249.211zm.284-.347l-.008.056a.386.386 0 00.009-.084l-.001.028zM30.71 57.57v.003l.007.007-.007-.01zm78.778-11.771l-.086.148a.386.386 0 01-.133-.538c-.144.231-.224.473-.415.611l.158.489-.028.071-.264-.386-.153.392a4.548 4.548 0 00-.384.637.879.879 0 00-.165.358l-.446.668a1.018 1.018 0 00-.217.335c-.135.157-.277.243-.456.373l.138.427-.03.038-.192-.383-.163.211.195.408a2.236 2.236 0 01-.121.147.385.385 0 01-.116-.491c-.099.19-.303.374-.5.565a.37.37 0 00-.097.152c-.047.134-.162.219-.27.313-.122.107-.247.215-.353.342a.889.889 0 00-.024.032l-.506.759-.212.255.178.388-.001.002-.179-.387-1.032 1.216c-.336.377-.725.86-1.116 1.239-.528.454-.938.904-1.347 1.355l-1.138 1.151c-.274.264-.658.525-1.041.789a.36.36 0 00-.079.072l-.005-.001v-.077c.325-.951.548-1.854 1.098-2.807a.11.11 0 00.008-.015c.069-.134.182-.332.21-.533.166-.392.423-.654.588-1.002.276-.38.453-.761.623-1.143a.755.755 0 00.137-.213.364.364 0 00.037-.145l.001-.134c0-.056.034-.136.064-.196l.275-.477c.16-.217.272-.534.492-.798a.425.425 0 00.063-.107c.156-.403.367-.705.626-1.055l.199-.313a.39.39 0 00.051-.116c.099-.382.357-.663.556-.902a.51.51 0 00.045-.069c.091-.175.24-.31.363-.456.116-.139.216-.283.278-.445.018-.024.047-.038.062-.055a.507.507 0 00.066-.08c.008-.012.016-.023.022-.035l.978-.993c.423-.408.845-.769 1.372-1.026l.241-.137h.242c.054 0 .113.048.175.079.099.049.197.097.282.124a.394.394 0 00.118.019c.016 0 .031.002.062.017a.43.43 0 00.05.019c.09.029.179.097.28.143.1.046.207.081.323.093.103.04.238.06.377.06h.204c.026.012.053.023.079.033a1.24 1.24 0 00-.14.393l-.122.196.215.396zM30.775 57.027l-.058.167v.14l.058.08v-.387zm22.272-.065a.777.777 0 01-.112-.235l.001-.002a.328.328 0 01-.001.002.322.322 0 00-.01.079c0 .071.02.138.054.196l.045-.03a.229.229 0 01.023-.01zm26.399-.018l.003.015a.36.36 0 01-.093.012s.038-.008.09-.027zm-.352-.076a.383.383 0 00.262.103s-.148-.002-.262-.103zm-25.935.058l-.176-.176c0-.062.012-.113.032-.155a.935.935 0 01.065-.049l-.045.014a.291.291 0 00-.02.035.294.294 0 00-.079.13.394.394 0 00.145.225l.078-.024zm26.051-.452l.089.22-.141-.112.013-.022h-.001l.04-.086zm-.255-.41l-.04.102.057.082c.013.002.026.002.039.002l-.052-.183-.004-.003zm12.633.067c-.012.037-.023.072-.036.104.035.01.071.015.108.015l-.072-.119zm.406-.073l.01-.019a.332.332 0 01-.033.053l.023-.034zm-15.462.012l-.207-.209v.003l.207.206zm15.155-.259l-.022.042.11.176-.088-.218zm-37.213-.138a.388.388 0 01-.054-.197c0-.084.007-.16.017-.229a.39.39 0 00.001.458l.036-.032zm37.471-.313v.002l.002.002-.002-.004zm15.283-.305l-.031.03a.387.387 0 00.273.113l-.001-.005a.388.388 0 01-.241-.138zm-46.811-.527a.412.412 0 01-.202.142c-.066.024-.119.029-.119.029a.386.386 0 00.321-.171zm-.366.06l-.001.009.046.047-.045-.056zm23.074-.257l-.002.007.085.084-.083-.091zm-22.644.002l.002-.021-.003.042.001-.021zm23.17-1.648v.001l.075.074-.075-.075zm-5.141-.367a.374.374 0 00.02.13c.013.038.032.07.054.097a.378.378 0 01-.074-.227zm5.34-.273c-.024.04-.049.078-.069.119a.386.386 0 00.175.042l-.106-.161zm-5.055 0a.271.271 0 00-.051.01l.068-.012-.017.002zm.031-.003l-.012.001.025-.001h-.013zm5.479-.058l-.024.043a.364.364 0 00.034-.065l-.01.022zm-.33-.212l-.004.011.1.146-.096-.157zm-4.797-.057l.006.002v-.004l-.006.002zm-44.724-.414l-.206.042a.388.388 0 00.379.309s-.109-.171-.173-.351zm86.165-.538l-.108.083a.385.385 0 00.297.141l-.066-.231-.123.007zm-82.778-.218a.99.99 0 01-.162.298c.03.054.052.088.052.088a.364.364 0 01-.109-.016l.057-.072a1.808 1.808 0 01-.115-.243h-.005l-.173-.055-.041.013a.386.386 0 00.277.357c-.037.045-.063.072-.063.072a.387.387 0 00.345-.213v-.229h-.063zm73.154.402l-.003.002.043.038-.04-.04zm-17.801-.151l.002.128a.354.354 0 00.073.007s-.034-.055-.075-.135zm-55.908-.219l-.268.086a.388.388 0 00.255.251l.113.017-.014-.038a2.45 2.45 0 01-.086-.316zm73.413.114l-.027.024a.329.329 0 00.244.211l-.051-.088-.166-.147zm.069-.055a.617.617 0 00-.048.038l.122.121.023.043.096.084.007-.002-.126-.125a1.715 1.715 0 01-.074-.159zm10.327.223l-.012.004-.052.053a.344.344 0 00.064-.057zm-.158-.155l-.007.003.051.169-.044-.172zm-27.826-.094a1.263 1.263 0 00-.184.114.38.38 0 00.106.126c.054-.07.104-.119.134-.108a1.806 1.806 0 01-.056-.132zm17.55.115a2.406 2.406 0 00-.052.05.41.41 0 00.068.07l-.016-.12zm10.452.113a.443.443 0 00.039-.06.404.404 0 01-.049.063l.01-.003zm.738-.689zm-37.142-.127l-.008.019.059.059-.051-.078zm-34.203-.413c-.076.192-.241.38-.241.38a.387.387 0 00.386-.371l-.145-.009zm-.587-.025c-.09.017-.189.019-.267.019l.006.03c.034.148.15.26.293.292l.084.009-.016-.038a2.233 2.233 0 01-.1-.312zm47.86-.979a.385.385 0 00-.314-.271c.229.038.23.21.167.382h.1c.015-.038.03-.075.047-.111zm-12.47-.151l-.02.044.006.009.098.097-.084-.15zm-21.919.031l-.048.007a.37.37 0 00.048-.007zm34.729-.481a.385.385 0 00-.177.324v.002h.007l.003-.004.167-.322zm-5.019.004a.382.382 0 00.168-.167.383.383 0 01-.176.16l.008.007zm-29.998-.295v.001a.356.356 0 000-.001zm.329-.325a.327.327 0 00-.279.16l.265.265.014-.039v-.386zm29.879.303l.001-.028a.364.364 0 01-.004.057l.003-.029zm-64.345 0l-.064-.064.011.027.052.041.001-.004zm58.766-1.246c-.099.1-.211.164-.211.164a.389.389 0 00.227-.073.464.464 0 00-.016-.091zm-10.474-16.77l-.001.005-.356-.353v.107c0 .288-.187.526-.399.772l-.249.192.178.542-.035.145a.387.387 0 01-.292-.455c-.168.808-.448 1.562-.728 2.263-.287.72-.69 1.385-.977 2.105a.196.196 0 00-.012.034c-.06.203-.18.369-.272.534-.065.115-.121.23-.159.349a1.176 1.176 0 00-.34.577c-.046.167-.065.345-.09.505-.27.429-.493.906-.714 1.385l-.782 1.076a.425.425 0 00-.035.058l-.38.786c-.332.392-.564.931-.847 1.314l.219.435-.011.024-.251-.386-.147.331a1.368 1.368 0 00-.266.532 2.348 2.348 0 00-.365.524c-.2.25-.306.505-.517.708-.179.172-.338.437-.348.696-.424.301-.626.697-.918 1.204-.128.181-.366.425-.49.723a.702.702 0 01-.11.178c.053-.588.109-1.005.214-1.565l.005-.027c.055-.482.218-.964.281-1.445.052-.146.066-.341.066-.539v-.591l.05-.534c.065-.166.102-.356.135-.552.039-.222.063-.457.199-.641a.391.391 0 00.076-.23c0-.618.337-1.127.55-1.692a.355.355 0 00.019-.071c.111-.641.448-1.333.67-1.921.346-.889.806-1.889 1.096-2.779.34-.762.683-1.37.969-2.087l.442-1.01c.402-.564.64-1.181.932-1.8l.007-.017c.22-.53.551-1.113.881-1.591l.016-.025c.515-.883 1.088-1.655 1.604-2.483l.013-.023a.378.378 0 00.073-.047c.212-.17.359-.387.491-.626.098-.176.188-.365.316-.541l.938-1.17.114-.074a.373.373 0 00.139-.15.38.38 0 01.197-.163.619.619 0 00-.006.096c0 .057.047.223.06.266a.388.388 0 00.018.082c.041.118.037.198.037.317 0 .175.009.351-.037.483a.43.43 0 00-.018.079l-.286 2.316-.162.883a1.113 1.113 0 00-.072.45l.033.033-.003.002-.03-.031v.056a1.416 1.416 0 00-.18.172.536.536 0 00-.108.322l.042.456c-.324.284-.368.676-.438 1.085l.351.417zm15.402 16.76a.39.39 0 00.216-.129.39.39 0 01-.214.081h-.009l.007.048zm-5.968-.308l-.129.199a.397.397 0 00.211.062l-.082-.261zm5.959.246l.002.014h.009a.31.31 0 00.165-.061.356.356 0 00.139-.246l.001-.021-.316.314zm-5.67-.046l.021-.014-.021.014c-.008.006-.018.011-.027.016l.027-.016zm-41.492-.769l.019-.031-.061.022-.002.006.044.003zm.015-.289a.827.827 0 01-.045.245l.005-.003a.582.582 0 00.04-.062.533.533 0 00.028-.106c-.005-.014-.015-.043-.028-.074zm23.841-.5l-.228-.228-.001.002.229.226zm5.441-.803a.95.95 0 01-.201.151c.058.056 0 .056 0 .056-.053.119-.11.235-.17.347.052.025.11.039.17.039 0 0 .213-.364.201-.593zM46.01 25.499h-.057c-.232.135-.498.2-.77.217a.384.384 0 01-.134.053c-.101.02-.199.086-.3.149-.165.104-.332.212-.497.276a.385.385 0 01-.139.025h-.172c-.208 0-.413.084-.579.204a.316.316 0 01-.059.035 1.927 1.927 0 01-.595.171c-.138.02-.263.019-.397.147a.388.388 0 01-.249.108h-.134a.328.328 0 01-.098-.015.488.488 0 01-.158.068l.042-.004c-.239.046-.39.138-.614.232l-.117.1a.431.431 0 00-.167.287c-.055.371-.168.688-.168 1.218 0 .081-.067.179-.135.258-.047.23-.149.438-.257.638-.078.146-.165.283-.188.435a.416.416 0 01-.02.079c-.214.566-.493 1.076-.493 1.692 0 .198-.074.278-.125.327a.38.38 0 01-.114.079l-.741 1.57c-.016.269-.107.523-.326.699l-.074.357v.015a.358.358 0 01-.075.231c-.083.124-.12.252-.163.457-.177.908-.586 1.761-.821 2.386l-.013.03c-.33.688-.546 1.641-.656 2.435a.354.354 0 01-.018.073l-.337.973c-.175.788-.355 1.465-.643 2.034l-.233.852a.884.884 0 01.333-.099c.165-.33.486-.428.83-.495l.154-.036a.67.67 0 01.228-.259.694.694 0 01.395-.103c.052 0 .101.01.145.029l.126.048-.02-.101c.48-.205.856-.356 1.282-.716a.39.39 0 01.188-.086c.142-.022.293-.096.452-.17.179-.083.364-.17.55-.231a1.27 1.27 0 01.107-.033l-.006.008c.127-.017.301-.011.301-.011s-.051-.011-.078-.011c.204 0 .371.158.386.358l.001.083a.414.414 0 01-.016.117c.147-.084.298-.174.439-.243a.787.787 0 01.336-.093c.026-.013.046-.032.067-.049.056-.043.108-.085.16-.118l.015-.01c-.129-.016-.294-.062-.391-.156a.387.387 0 01.238-.663.733.733 0 01.129-.041c.285-.167.616-.372.896-.482l.511-.246a.792.792 0 01.266-.154c.376-.159.701-.37 1.134-.63a.388.388 0 00-.188.336l.007.007.091-.103.076.168-.001-.021.001.022.079.176.134.133.03-.055a.409.409 0 01-.07-.055l-.054-.052a.387.387 0 01.04-.594c.259-.187.465-.361.77-.437.421-.252.792-.458 1.112-.714a.387.387 0 01.158-.076l.589-.131a.724.724 0 01.142-.093l.018-.032a.397.397 0 01.278-.19l.001-.001c.268-.118.575-.365.785-.466.413-.199.777-.392 1.087-.74a.386.386 0 01.215-.122c.227-.044.402-.185.621-.353.07-.067.19-.169.275-.212.051-.025.1-.04.146-.047.163-.046.246-.138.375-.221a.386.386 0 01.209-.061c.025 0 .054-.018.086-.032.038-.017.077-.037.113-.059a.386.386 0 01.273-.283c.38-.104.702-.373 1.027-.53a.388.388 0 00-.193.486c.037-.019.075-.036.116-.052a.389.389 0 01-.027-.141c0-.137.059-.218.126-.265l-.006-.014.055-.053.013.032a.297.297 0 00-.062.035l.051.128c-.005.068.002.148.013.225a1.416 1.416 0 00-.163.053.384.384 0 00.191.207l-.08-.217.036.025-.001.01.038.039-.005-.026-.032-.023a.075.075 0 01.02-.042l-.004-.026c.023-.005.047-.011.071-.015l-.084-.21a.343.343 0 01.027-.121l-.016-.042a.372.372 0 01.129-.031h.005l-.033.003a.12.12 0 00-.085.07l.157.383a.866.866 0 01.082-.102c.005-.1.016-.205.04-.286-.03-.041-.081-.067-.161-.068.08-.002.133.018.166.053l-.005.015c.038.052.044.129.032.213l.016-.016c.012-.086.004-.163-.043-.212.039-.115.107-.169.226-.054l.062.06c.12-.089.245-.166.357-.216.158-.172.353-.326.563-.472a.511.511 0 01-.028-.124v-.022l.098.098.001-.001-.099-.1v-.053l.131.131.008-.005a.387.387 0 01-.082-.238l.001-.047-.014-.023.019-.035c.015-.165.065-.36.136-.476a.48.48 0 01.417-.249c.079 0 .133-.067.199-.127.149-.137.3-.309.479-.453l.023-.017c.373-.256.654-.555 1.047-.779a.446.446 0 01.206-.186.382.382 0 01.044-.193l.006-.009a.39.39 0 01.28-.224c.084-.016.132-.072.185-.129.078-.082.156-.175.253-.268a.38.38 0 01.059-.047c.307-.197.454-.451.659-.697a.44.44 0 01.029-.032c.283-.272.567-.647.901-.928l.314-.454c.362-.523.618-1.037 1.252-1.449.026-.034.053-.066.071-.087a.368.368 0 01.057-.126c.034-.05.024-.103.034-.153a.874.874 0 01.11-.301.468.468 0 01-.08-.064.537.537 0 01-.133-.37.387.387 0 01.173-.322v-.011.011l.007-.005-.007-.007v-.053l.04.04a.772.772 0 01.155-.062l-.106-.226c.091-.11.099-.251.119-.374.02-.125.043-.241.079-.342v-.031l.009.008.001-.002-.01-.01a.84.84 0 00-.078-.346c-.307-.221-.821-.388-1.244-.433l-.032-.005c-.261-.05-.522-.048-.731-.048a.37.37 0 01-.074-.007 7.415 7.415 0 00-1.479-.159c-.328 0-.656-.001-1.039.052a.47.47 0 01-.053.003l-1.782.056a.407.407 0 01-.099-.013l-.335-.044c-.048-.002-.098-.005-.146.018a.39.39 0 01-.168.039s-.651 0-.65-.001c-.264.129-.488.146-.763.252a.401.401 0 01-.118.025c-1.015.054-1.973.381-3.043.547-.574.166-1.203.376-1.885.394a1.204 1.204 0 01-.284.166c-.078.034-.165.05-.233.115a.378.378 0 01-.207.103c-.346.056-.584.109-.866.116h-.115zm23.36 18.843l-.005.001.013-.001h-.008zm22.01-.177a.385.385 0 00-.149-.487c.191.125.152.295.059.437a1.3 1.3 0 01.09.05zm-41.886-1.307a3.685 3.685 0 01-.156.124.386.386 0 00.294.137s-.076-.118-.138-.261zm62.999.125l.032-.032.038-.317.173.041v-.001l-.214-.087a1.07 1.07 0 01-.074.321l.003.024.021.022c.03 0 .029.015.021.029zm-.05-.061a.399.399 0 01-.086-.19h-.154c.145-.144.214-.009.245.176l-.005.014zm-61.01-1.097a5.682 5.682 0 00-.177.11.388.388 0 00.331.186s-.089-.137-.154-.296zm34.213-.811l-.173-.318a.114.114 0 00-.021.03.389.389 0 00-.003.35.287.287 0 01.174-.061l.023-.001zm-40.706-.495l-.03.016.025.014.03-.031-.003-.014-.022.015zm-.022-.051l.035-.013-.008-.04-.005.004-.016.039-.006.01zm-.331-.294a.264.264 0 00.052.13l-.052-.13zm.184-.254a.229.229 0 00-.137.083.265.265 0 00-.023.039l.097.239.034-.052a1.66 1.66 0 01.029-.309zm32.358-.053l-.019.033.061.061-.042-.094zm-29.793-.922l.012.04a.375.375 0 00.157.034l-.003-.005a.4.4 0 01-.166-.069zm.342.004l-.065.039.01.004.016-.004.039-.039zm-.543-.206a.39.39 0 00.16.214l.033-.018a.39.39 0 01-.136-.196h-.057zm.255.163l-.057.03-.056-.193h.083l.014.031.031.065.023.045-.038.022zm-.102-.594l-.012.025-.042.02a.38.38 0 01.054-.045zm-21.135-.939l-.01.011c.03.094-.011.203-.072.3l.047.116-.05-.11c-.096.152-.238.276-.238.276l.022-.001a.38.38 0 00.295-.165h-.029l.041-.017a.383.383 0 00.003-.402l-.009-.008zm-1.303-.133l-.018.049a.367.367 0 01-.094.012s.049-.021.112-.061zm41.359-1.098l.261.26-.26-.262-.001.002zm.03-.078l.255.252-.254-.254-.001.002zm-42.692-.156a.342.342 0 00.177.322c.094.057.193.071.207.073l-.384-.395zm28.386-.187a.538.538 0 01.172-.024h.069a.29.29 0 00.041-.016c-.076-.125-.224-.148-.264-.15h-.017l-.001.19zm1.202-.261a.936.936 0 01-.023.056l.002.006.022-.047-.001-.015zm-.175-.126l-.046.013a.079.079 0 00-.025.019l.012.065.098.069.012-.038-.051-.128zm-15.253-.183l.021.039.061.061-.082-.1zm-14.727-.319a.33.33 0 00.102.169c.03.028.109.059.152.074l-.257-.259.003.016zm-.006-.037l.001.006-.002-.017.001.011zm38.885-.934l-.021.013.084.277.002-.003-.065-.287zm-7.052.117v-.122l.007.011a.882.882 0 00-.007.111zM38.99 32.063l-.101.214a.387.387 0 00.165.037s-.036-.112-.064-.251zm-4.754-1.347l-.119-.119.044.044a.38.38 0 01-.052.046v.045l.077.112.05-.128zm-8.932.054a.17.17 0 00-.015.028l.022-.039-.007.011zm8.971-.156a1.345 1.345 0 00-.019-.149.393.393 0 01-.095.176l.075.074.039-.101zm-.163-.022l.003.003h.001l-.004-.003zm-.28-.204a1.94 1.94 0 00-.195.066.383.383 0 00.233.137l.026-.068a3.163 3.163 0 01-.064-.135zm.277-.128c-.029.005-.062.026-.101.065a.314.314 0 00-.049.113l.15.15-.082-.082.082-.082v-.164zm-.156.173l.005.006-.003.017c.005.027.016.06.026.086l.007.003.039-.038-.069-.068.001-.001-.006-.006v.001zm.298.013l-.025.046s.014-.018.025-.046zm43.646-2.976l-.267-.267-.001.003.268.264zm-16.364-1.084v-.108l.053.055-.053.053zm.266-.388l.011.011.011-.01-.014-.009-.008.008zm-16.114-.794c-.063.03-.129.054-.197.073a.387.387 0 00.35.222s-.089-.137-.153-.295zm25.777-.002l-.183-.182.005.008.178.174zm-24.03-.473c-.083.057-.175.089-.265.128a.386.386 0 00.338.199l-.073-.327zm.107-.076l.081.348v-.387l-.081.039zm14.217.338l-.107-.107.002.004.105.103zM72 24.168l-.264-.266-.001.002.265.264zm-6.638-.281a.397.397 0 00.062-.263.311.311 0 01-.082.237l.02.026zm-27.863-.233c-.067-.186-.087-.384.111-.418a.386.386 0 00-.308.484 2.07 2.07 0 01.197-.066zm.773-.267a.385.385 0 00-.223-.147c.146.038.156.175.118.323a.357.357 0 00.082-.057.28.28 0 01.023-.119zm27.119.122l-.009-.017a.211.211 0 01.016.034l-.007-.017zm7.525-.398l-.229-.231v-.054l-.002.002.001.051.001.001v.003l.229.228zm.078-.057l-.191-.314a.221.221 0 00-.094.057l.274.271.011-.014zm-.307.009v-.18l-.001-.002v-.002l-.02-.02-.001.002.021.02.001.182zm4.54-.631a.39.39 0 00.064.058l.053.183a.385.385 0 01-.242-.085l.125-.156zm-3.794-.311h.001c0 .11 0 .166.058.166a.27.27 0 00.093-.025l-.152-.331v.19zm.355-.021a.406.406 0 00-.053-.094.32.32 0 00-.279-.102l.142.352a.465.465 0 00.124-.08l.066-.076zm4.848-.427c.06.043.112.107.145.171 0 0-.057.11-.115.11l-.049.034a.387.387 0 01-.123.021s.088-.161.142-.336zm-4.627.149l-.155.068.04.087.115-.133v-.022zm4.211-.121c.012.03.025.059.038.087a.818.818 0 00-.112.142.383.383 0 01-.119-.148c.065-.027.13-.053.193-.081zm-4.787.207v.011l.012-.013-.012.002zm.406-.393a.28.28 0 00-.092.143l.101.22.144-.238a.454.454 0 01-.04-.018c-.052 0-.103-.089-.113-.107zm-25.34-1.518l-.001.018.001-.018zm.837-.257c-.008.001-.018.002-.027.005a.097.097 0 01.019.029l.008-.034zm9.547-.02l.01.019-.01-.019zm-.741.018c.008 0 .057-.004.057-.055.057-.111.057-.166.115-.166.011 0 .022.002.033.006-.005-.069-.033-.124-.095-.152a.351.351 0 00-.092-.019h-.017l-.001.386zm.311-.172l-.001.001a.388.388 0 01.001-.001zm-.633.041a.377.377 0 01.003-.019l-.003.019-.005.029.005-.029zm.629-.054a.373.373 0 00-.016-.035l.016.035z"
|
||
/>
|
||
</g>
|
||
</svg>
|
||
|
||
</a>
|
||
</nav>
|
||
<div
|
||
id="contextMenu"
|
||
class="opacity-0 absolute -z-1 -translate-y-2.5 bg-white shadow-lg rounded-2xl p-2 ring-1 ring-navy-950/10 shadow-navy-950/[.075] top-full -mt-3 left-8 transition-all"
|
||
>
|
||
<a
|
||
class="group relative flex flex-col whitespace-nowrap px-3 py-2 text-navy-950 hocus:text-violet-950 transition-colors"
|
||
href="https://fly.io/docs/about/brand/"
|
||
target="_blank"
|
||
>
|
||
<span class="absolute inset-0 scale-90 rounded-lg group-hover:scale-100 group-focus:scale-100 group-hover:bg-violet-100 group-focus:bg-violet-100 transition-all"></span>
|
||
<strong class="relative text-sm font-semibold">
|
||
Need a Logo?
|
||
</strong>
|
||
<span class="relative flex items-center text-[0.8125rem] font-medium text-navy-700/70 group-hover:text-violet-800/70 group-focus:text-violet-800/70 transition-colors">
|
||
View Our Brand Assets
|
||
<svg
|
||
viewBox="0 0 16 16"
|
||
fill="currentColor"
|
||
class="relative size-4 ml-0.5 -mr-1"
|
||
>
|
||
<path fill-rule="evenodd" d="M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
|
||
</svg>
|
||
</span>
|
||
</a>
|
||
</div>
|
||
<script>
|
||
const [logo, contextMenu] = ['logo', 'contextMenu'].map(id => document.getElementById(id))
|
||
|
||
logo.addEventListener('contextmenu', e => {
|
||
e.preventDefault()
|
||
contextMenu.classList.remove('-z-1', 'opacity-0', 'pointer-events-none', '-translate-y-2.5')
|
||
contextMenu.classList.add('z-[60]')
|
||
})
|
||
|
||
document.addEventListener('click', e => {
|
||
if (!contextMenu.contains(e.target) && e.target !== logo) {
|
||
contextMenu.classList.add('-z-1', 'opacity-0', 'pointer-events-none', '-translate-y-2.5')
|
||
contextMenu.classList.remove('z-[60]')
|
||
}
|
||
})
|
||
</script>
|
||
|
||
|
||
<button data-menu-toggle class="ml-auto menu-toggle lg:hidden relative z-[60] -scale-x-100 rounded-full bg-white [[data-menu-state=on]_&]:shadow-sm border [[data-menu-state=off]_&]:border-transparent bg-clip-padding transition-colors flex-none flex items-center justify-center w-8 h-8 -mx-2">
|
||
<span class="sr-only">Open main menu</span>
|
||
<svg data-menu-button class="absolute cursor-pointer transition-transform duration-[400ms] select-none [[data-menu-state=on]_&]:rotate-45" viewBox="0 0 100 100" width="30">
|
||
<path class="fill-none transition-all duration-[400ms] delay-400 stroke-current stroke-[5.5] [stroke-linecap:round] [stroke-dasharray:40_121] [[data-menu-state=on]_&]:[stroke-dashoffset:-68px]" d="m 70,33 h -40 c 0,0 -8.5,-0.149796 -8.5,8.5 0,8.649796 8.5,8.5 8.5,8.5 h 20 v -20" />
|
||
<path class="fill-none transition-all duration-[400ms] delay-400 stroke-current stroke-[5.5] [stroke-linecap:round]" d="m 55,50 h -25" />
|
||
<path class="fill-none transition-all duration-[400ms] delay-400 stroke-current stroke-[5.5] [stroke-linecap:round] [stroke-dasharray:40_121] [[data-menu-state=on]_&]:[stroke-dashoffset:-68px]" d="m 30,67 h 40 c 0,0 8.5,0.149796 8.5,-8.5 0,-8.649796 -8.5,-8.5 -8.5,-8.5 h -20 v 20" />
|
||
</svg>
|
||
</button>
|
||
|
||
<nav
|
||
aria-label="Main menu"
|
||
class="pointer-events-auto hidden lg:flex w-full items-center justify-end"
|
||
>
|
||
<div class="hidden xl:flex items-center absolute left-1/2 -translate-x-1/2 px-3 text-sm font-medium">
|
||
<dl class="flex-none bubble-wrap hidden shrink-0 xl:flex group relative px-3 py-2.5 cursor-pointer">
|
||
<dt class="flex items-center justify-items-center whitespace-nowrap transition-colors text-violet-600">
|
||
Articles
|
||
</dt>
|
||
<dd class="bubble-b tail text-sm text-navy flex flex-col w-44 rounded-2xl p-2">
|
||
<div class="rounded-tl w-3 h-3 absolute top-0 left-1/2 z-[-1] -ml-2 rotate-45 bg-white -mt-1.5">
|
||
</div>
|
||
<a
|
||
class="relative whitespace-nowrap px-3 py-2.5 before:absolute before:inset-0 before:z-[-1] before:rounded-lg before:transition-all transition-colors before:bg-violet-100 before:scale-100 text-violet-600"
|
||
href="/blog/"
|
||
>
|
||
Blog
|
||
</a>
|
||
<a
|
||
class="relative whitespace-nowrap px-3 py-2.5 before:absolute before:inset-0 before:z-[-1] before:rounded-lg before:transition-all transition-colors before:scale-90 hocus:before:scale-100 hocus:before:bg-violet-100 hocus:text-violet-600"
|
||
href="/sprites-blog/"
|
||
>
|
||
Sprites
|
||
</a>
|
||
<a
|
||
class="relative whitespace-nowrap px-3 py-2.5 before:absolute before:inset-0 before:z-[-1] before:rounded-lg before:transition-all transition-colors before:scale-90 hocus:before:scale-100 hocus:before:bg-violet-100 hocus:text-violet-600"
|
||
href="/infra-log/"
|
||
>
|
||
Infra Log
|
||
</a>
|
||
</dd>
|
||
</dl>
|
||
<a
|
||
href="/security/"
|
||
class="text-center mx-3 transition-colors hover:text-violet-600"
|
||
>
|
||
Security
|
||
</a>
|
||
<a
|
||
href="/customer-stories/"
|
||
class="text-center mx-3 transition-colors hover:text-violet-600"
|
||
>
|
||
Customers
|
||
</a>
|
||
<dl class="flex-none bubble-wrap hidden shrink-0 xl:flex group relative px-3 py-2.5 cursor-pointer">
|
||
<dt class="flex items-center justify-items-center whitespace-nowrap transition-colors group-hover:text-violet-600 group-focus-within:text-violet-600">
|
||
Docs
|
||
</dt>
|
||
<dd class="bubble-b tail text-sm text-navy flex flex-col w-44 rounded-2xl p-2">
|
||
<div class="rounded-tl w-3 h-3 absolute top-0 left-1/2 z-[-1] -ml-2 rotate-45 bg-white -mt-1.5">
|
||
</div>
|
||
<a
|
||
class="relative whitespace-nowrap px-3 py-2.5 before:absolute before:inset-0 before:z-[-1] before:rounded-lg before:transition-all transition-colors before:scale-90 hocus:before:scale-100 hocus:before:bg-violet-100 hocus:text-violet-600"
|
||
href="/docs/"
|
||
>
|
||
Platform Docs
|
||
</a>
|
||
<a
|
||
class="relative whitespace-nowrap px-3 py-2.5 before:absolute before:inset-0 before:z-[-1] before:rounded-lg before:transition-all transition-colors before:scale-90 hocus:before:scale-100 hocus:before:bg-violet-100 hocus:text-violet-600"
|
||
href="https://docs.sprites.dev/"
|
||
>
|
||
Sprites Docs
|
||
</a>
|
||
</dd>
|
||
</dl>
|
||
<a
|
||
href="https://community.fly.io"
|
||
class="text-center mx-3 transition-colors hover:text-violet-600"
|
||
>
|
||
Community
|
||
</a>
|
||
<a
|
||
href="https://status.flyio.net"
|
||
class="text-center mx-3 transition-colors hover:text-violet-600"
|
||
>
|
||
Status
|
||
</a>
|
||
<a
|
||
href="/pricing/"
|
||
class="text-center mx-3 transition-colors hover:text-violet-600"
|
||
>
|
||
Pricing
|
||
</a>
|
||
</div>
|
||
<div class="ml-5 flex-none flex items-center">
|
||
<a
|
||
href="https://fly.io/app/sign-in"
|
||
class="ml-auto text-sm button-sm border border-gray-300 shadow-sm hover:border-violet-200 hover:bg-violet-200 hover:text-violet-600 hover:text-shadow-none hover:shadow-none transition-all"
|
||
>
|
||
Sign In
|
||
</a>
|
||
<a
|
||
href="/docs/hands-on/start/"
|
||
class="text-sm mx-3 button-sm bg-violet-500 hover:bg-violet-600 text-white transition-all"
|
||
>
|
||
Get Started
|
||
</a>
|
||
<a
|
||
href="/blog/feed.xml"
|
||
target="_blank"
|
||
class="flex items-center p-2 ml-0 -mr-2 hover:text-violet-600 transition-all"
|
||
tabindex=""
|
||
>
|
||
|
||
<svg role="img" class="relative top-px shrink-0" viewBox="0 0 20 20" style="pointer-events: none; width: 18px; height: 18px;" fill="currentColor">
|
||
<g buffered-rendering="static">
|
||
<path d="M5 3a1 1 0 000 2c5.523 0 10 4.477 10 10a1 1 0 102 0C17 8.373 11.627 3 5 3z" />
|
||
<path d="M4 9a1 1 0 011-1 7 7 0 017 7 1 1 0 11-2 0 5 5 0 00-5-5 1 1 0 01-1-1zM3 15a2 2 0 114 0 2 2 0 01-4 0z" />
|
||
</g>
|
||
</svg>
|
||
<span class="sr-only">RSS Feed</span>
|
||
</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="lg:hidden opacity-0 z-[-1] pointer-events-none [[data-menu-state=on]_&]:pointer-events-auto [[data-menu-state=on]_&]:opacity-100 [[data-menu-state=on]_&]:z-40 transition-all duration-500 fixed inset-0 bg-gray-500/25 backdrop-blur-sm"></div>
|
||
<nav
|
||
data-menu
|
||
aria-label="Main menu"
|
||
class="lg:hidden [[data-menu-state=on]_&]:translate-x-0 -translate-x-full transition duration-300 ease-in-out text-sm w-full sm:max-w-sm md:max-w-[25rem] fixed left-0 top-0 bottom-0 z-50 border-t border-t-gray-200 bg-clip-padding pl-[calc(50vw-240px)] sm:pl-[calc(50vw-320px+1.5rem)] md:pl-[calc(50vw-384px+1.5rem)] pr-6 pt-24 bg-white shadow-[1px_0_rgba(86,75,128,0.1)]"
|
||
>
|
||
<div class="max-h-full overflow-y-auto scrollbar-hidden grid justify-start pb-8 pl-4 sm:pl-0">
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-violet-600"
|
||
href="/blog/"
|
||
>
|
||
Blog
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="/sprites-blog/"
|
||
>
|
||
Sprites
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="/infra-log/"
|
||
>
|
||
Infra Log
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="/security/"
|
||
>
|
||
Security
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="/customer-stories/"
|
||
>
|
||
Customers
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="/docs/"
|
||
>
|
||
Platform Docs
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="https://docs.sprites.dev/"
|
||
>
|
||
Sprites Docs
|
||
<span class="sr-only">(opens an external site)</span>
|
||
<svg role="img" width="14" height="14" class="inline-flex ml-2 self-center pointer-events-none" viewBox="0 0 14 14"><g buffered-rendering="static" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"><path d="M12.625 4.825c0-2.318-1.882-4.2-4.2-4.2h-3.6a4.202 4.202 0 00-4.2 4.2v3.6c0 2.318 1.882 4.2 4.2 4.2h3.6c2.318 0 4.2-1.882 4.2-4.2v-3.6zM4.482 8.625l4-4"/><path d="M8.482 7.297V4.625H5.81"/></g></svg>
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="https://community.fly.io"
|
||
>
|
||
Community
|
||
<span class="sr-only">(opens an external site)</span>
|
||
<svg role="img" width="14" height="14" class="inline-flex ml-2 self-center pointer-events-none" viewBox="0 0 14 14"><g buffered-rendering="static" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"><path d="M12.625 4.825c0-2.318-1.882-4.2-4.2-4.2h-3.6a4.202 4.202 0 00-4.2 4.2v3.6c0 2.318 1.882 4.2 4.2 4.2h3.6c2.318 0 4.2-1.882 4.2-4.2v-3.6zM4.482 8.625l4-4"/><path d="M8.482 7.297V4.625H5.81"/></g></svg>
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="https://status.flyio.net"
|
||
>
|
||
Status
|
||
<span class="sr-only">(opens an external site)</span>
|
||
<svg role="img" width="14" height="14" class="inline-flex ml-2 self-center pointer-events-none" viewBox="0 0 14 14"><g buffered-rendering="static" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"><path d="M12.625 4.825c0-2.318-1.882-4.2-4.2-4.2h-3.6a4.202 4.202 0 00-4.2 4.2v3.6c0 2.318 1.882 4.2 4.2 4.2h3.6c2.318 0 4.2-1.882 4.2-4.2v-3.6zM4.482 8.625l4-4"/><path d="M8.482 7.297V4.625H5.81"/></g></svg>
|
||
</a>
|
||
<a
|
||
class="flex items-center mr-auto text-sm py-1.5 transition-colors text-navy-950 hover:text-violet-600"
|
||
href="/pricing/"
|
||
>
|
||
Pricing
|
||
</a>
|
||
<a
|
||
href="https://fly.io/app/sign-in"
|
||
class="button mt-8 max-w-40 border border-gray-300 shadow-sm text-violet-600 hover:border-violet-500/40 hover:bg-violet-200 hover:text-violet-600 hover:text-shadow-none hover:shadow-none transition-all"
|
||
>
|
||
Sign In
|
||
</a>
|
||
<a
|
||
href="/docs/hands-on/start/"
|
||
class="button mt-3 max-w-40 bg-violet-600 hover:bg-violet-600 text-white transition-all"
|
||
>
|
||
Get Started
|
||
</a>
|
||
<a
|
||
href="/blog/feed.xml"
|
||
target="_blank"
|
||
class="flex items-center p-2 mt-3 text-navy-950 hover:text-violet-600 transition-all"
|
||
tabindex=""
|
||
>
|
||
|
||
<svg role="img" class="relative shrink-0" viewBox="0 0 20 20" style="pointer-events: none; width: 18px; height: 18px;" fill="currentColor">
|
||
<g buffered-rendering="static">
|
||
<path d="M5 3a1 1 0 000 2c5.523 0 10 4.477 10 10a1 1 0 102 0C17 8.373 11.627 3 5 3z" />
|
||
<path d="M4 9a1 1 0 011-1 7 7 0 017 7 1 1 0 11-2 0 5 5 0 00-5-5 1 1 0 01-1-1zM3 15a2 2 0 114 0 2 2 0 01-4 0z" />
|
||
</g>
|
||
</svg>
|
||
<span class="ml-1.5">RSS Feed</span>
|
||
</a>
|
||
</div>
|
||
</nav>
|
||
</header>
|
||
|
||
|
||
<main role="main" class="container mx-auto px-4 sm:px-6 lg:px-8 py-14 md:py-20">
|
||
<header class="max-w-[44rem] mx-auto mb-14 sm:mb-16">
|
||
<div class="flex flex-wrap items-center text-xs font-bold text-navy-500 uppercase tracking-wider mb-7">
|
||
Reading time
|
||
<span class="mx-2 text-gray-300">•</span>
|
||
21 min
|
||
<span class="flex-1 bg-gray-100 flex-1 h-px mx-2"></span>
|
||
<a
|
||
class="flex items-center justify-center w-7 h-7 hover:text-blue-500 transition-colors"
|
||
href="https://twitter.com/share?text=A Foolish Consistency: Consul at Fly.io&url=https://fly.io/blog/a-foolish-consistency/&via=flydotio"
|
||
target="_blank"
|
||
>
|
||
|
||
<svg role="img" class="" viewBox="0 0 24 24" style="pointer-events: none; width: 18px; height: 18px;" fill="currentColor">
|
||
<g buffered-rendering="static">
|
||
<path d="M22.208 3.871c-.757.252-1.824.496-2.834.748-.757-.883-1.892-1.388-3.154-1.388-2.902 0-4.92 2.649-4.289 5.425-3.659-.126-6.939-1.892-9.083-4.542-1.135 1.892-.505 4.542 1.388 5.803-.757 0-1.388-.126-2.019-.505 0 2.145 1.388 4.037 3.532 4.416-.631.252-1.388.252-2.019.126.505 1.766 2.145 3.028 4.037 3.028-1.892 1.388-4.289 2.019-6.56 1.766 1.892 1.262 4.163 2.019 6.686 2.019 8.2 0 12.742-6.813 12.49-12.994.753-1.089 1.49-2.201 1.824-3.902z" />
|
||
</g>
|
||
</svg>
|
||
<span class="sr-only">Share this post on Twitter</span>
|
||
</a>
|
||
<a
|
||
class="flex items-center justify-center w-7 h-7 hover:text-orange-500 transition-colors"
|
||
href="http://news.ycombinator.com/submitlink?u=https://fly.io/blog/a-foolish-consistency/&t=A Foolish Consistency: Consul at Fly.io"
|
||
target="_blank"
|
||
>
|
||
|
||
<svg role="img" class="" viewBox="0 0 24 24" style="pointer-events: none; width: 14px; height: 14px;" fill="currentColor">
|
||
<g buffered-rendering="static">
|
||
<path d="M16.063 2h4.75l-6.625 12.5v7.5h-4.126l.001-7.5-6.875-12.5h4.875l4.125 8.75 3.875-8.75z" />
|
||
</g>
|
||
</svg>
|
||
<span class="sr-only">Share this post on Hacker News</span>
|
||
</a>
|
||
<a
|
||
class="flex items-center justify-center w-7 h-7 hover:text-red-500 transition-colors"
|
||
href="http://www.reddit.com/submit?url=https://fly.io/blog/a-foolish-consistency/&title=A Foolish Consistency: Consul at Fly.io"
|
||
target="_blank"
|
||
>
|
||
|
||
<svg role="img" class="" viewBox="0 0 24 24" style="pointer-events: none; width: 20px; height: 20px;" fill="currentColor">
|
||
<g buffered-rendering="static">
|
||
<path d="M15.029 14.708c-.762 0-1.401-.616-1.401-1.377 0-.762.639-1.4 1.401-1.4s1.378.638 1.378 1.4c0 .761-.616 1.377-1.378 1.377m.194 2.546c-.674.673-1.727 1-3.224 1-1.496 0-2.551-.327-3.223-1-.07-.07-.11-.165-.11-.264 0-.205.169-.374.374-.374.099 0 .194.04.265.11.524.525 1.406.781 2.694.781s2.17-.256 2.696-.781c.07-.07.165-.109.264-.109.205 0 .373.168.373.373 0 .099-.039.194-.109.264m-7.631-3.923c0-.762.639-1.4 1.4-1.4.76 0 1.377.638 1.377 1.4 0 .76-.616 1.377-1.377 1.377-.762 0-1.4-.617-1.4-1.377m14.408-1.515c-.002-1.242-1.023-2.264-2.265-2.265-.569-.002-1.118.213-1.535.6-1.495-.974-3.497-1.602-5.714-1.688l1.223-3.734 3.213.757c.002 1.022.842 1.861 1.864 1.862 1.022-.001 1.863-.842 1.865-1.864-.002-1.023-.843-1.864-1.865-1.865-.746 0-1.423.448-1.716 1.134l-3.52-.828-.008-.002-.33-.078-1.51 4.61c-2.301.043-4.386.669-5.937 1.664-.411-.364-.943-.568-1.501-.568-1.241.001-2.262 1.023-2.264 2.264 0 .786.408 1.517 1.076 1.929-.038.221-.057.445-.057.673 0 3.288 4.01 5.964 8.939 5.964s8.94-2.676 8.94-5.964c0-.212-.016-.422-.049-.629.713-.398 1.155-1.155 1.151-1.972" />
|
||
</g>
|
||
</svg>
|
||
<span class="sr-only">Share this post on Reddit</span>
|
||
</a>
|
||
</div>
|
||
<h1 class="relative w-full font-heading text-navy-900 leading-tight sm:leading-tight lg:leading-tight 2xl:leading-tight text-3xl sm:text-4xl lg:text-[2.75rem]">
|
||
A Foolish Consistency: Consul at Fly.io
|
||
</h1>
|
||
</header>
|
||
|
||
<article class="xl:grid grid-cols-auto-span-auto items-start sm:text-lg leading-relaxed">
|
||
<dl class="text-sm w-52 relative top-[-6.5rem] hidden xl:block">
|
||
<dt class="sr-only">Author</dt>
|
||
<dd class="flex items-center space-x-3 mb-7">
|
||
<img alt="Thomas Ptacek" class="w-10 h-10 object-cover rounded-xl" src="/static/images/thomas.webp" />
|
||
<dl class="text-sm font-medium leading-5 whitespace-no-wrap">
|
||
<dt class="sr-only">Name</dt>
|
||
<dd class="text-navy-900">
|
||
Thomas Ptacek
|
||
</dd>
|
||
<dt class="sr-only">@tqbf</dt>
|
||
<dd class="text-violet-500 hover:text-violet-700 transition-colors">
|
||
<a href="https://twitter.com/tqbf" target="_blank">
|
||
@tqbf
|
||
</a>
|
||
</dd>
|
||
</dl>
|
||
</dd>
|
||
</dl>
|
||
|
||
<section class="relative max-w-[44rem] mx-auto">
|
||
<figure class="relative">
|
||
<img
|
||
class="post-cover"
|
||
src="/blog/a-foolish-consistency/assets/default-books.webp"
|
||
alt=""
|
||
>
|
||
<figcaption class="flex items-center absolute right-0 top-full pt-3 text-xs font-medium text-[#73739C]">
|
||
<span class="sr-only">Image by</span>
|
||
|
||
<svg
|
||
role="img"
|
||
class="mr-1.5"
|
||
style="pointer-events: none; width: 17px; height: 17px;"
|
||
viewBox="0 0 20 20"
|
||
fill="currentColor"
|
||
fill-rule="evenodd"
|
||
>
|
||
<g buffered-rendering="static">
|
||
<path fill-rule="evenodd" d="M1 8a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 018.07 3h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0016.07 6H17a2 2 0 012 2v7a2 2 0 01-2 2H3a2 2 0 01-2-2V8zm13.5 3a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zM10 14a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd" />
|
||
</g>
|
||
</svg>
|
||
|
||
<a href="https://annieruygtillustration.com/" target="_blank" class="text-navy-900 underline underline-offset-2 decoration-1 decoration-navy-900/30 hover:decoration-violet-600/30 hover:text-violet-600 transition-colors">
|
||
Annie Ruygt
|
||
</a>
|
||
</figcaption>
|
||
</figure>
|
||
<div class="lead"><p><a href="http://Fly.io" title="">Fly.io</a> runs applications by transmogrifying Docker containers into Firecracker micro-VMs running on our hardware around the world, connected with WireGuard to a global Anycast network. Yours could be one of them! <a href="https://fly.io/docs/speedrun/" title="">Check us out</a>: from a working container, your app can be running worldwide in minutes.</p>
|
||
</div>
|
||
<p>We set the scene, as usual, with sandwiches. Dig if you will the picture: a global Sandwich Bracket application, ascertaining once and for all the <a href='https://jpgraziano.com/' title=''>greatest sandwich on the planet</a>.</p>
|
||
|
||
<p><a href='http://Fly.io' title=''>Fly.io</a> wants our app, <code>sandwich-bracket</code>, deployed close to users around the world. Chicago users vote for <a href='https://www.tripadvisor.com/Restaurant_Review-g35956-d502500-Reviews-Johnnie_s_Beef-Elmwood_Park_Illinois.html' title=''>Italian beefs</a> on an instance of <code>sandwich-bracket</code> in Chicago; people who love bánh mì are probably voting on a Sydney instance, egg salad on white bread, Tokyo.</p>
|
||
|
||
<p>To run a platform that makes this kind of thing work, we need a way to route incoming traffic to instances. The way we do that is with service discovery: a distributed catalog of all services running at Fly.io. The Fly.io service catalog lives in <a href='https://www.consul.io/' title=''>Consul</a>. The catalog expands consciousness. The catalog is vital to space travel.</p>
|
||
|
||
<p>The catalog occupies more of our mental energy than just about anything at Fly.io. We’ve sunk a huge amount of energy into keeping São Paulo, Sydney, Singapore, and points between consistent in their view of what’s running on Fly.io, scaling a single global Consul cluster. What we think we’ve learned is that keeping São Paulo and Sydney on exactly the same page about what’s running in Mumbai is a mug’s game, and we shouldn’t be playing it.</p>
|
||
|
||
<p>And so, to begin, it is my privilege to inflict Consul on you.</p>
|
||
<h3 id='what-the-hell-is-consul' class='group flex items-start whitespace-pre-wrap relative mt-14 sm:mt-16 mb-4 text-navy-950 font-heading'><a class='inline-block align-text-top relative top-[.15em] w-6 h-6 -ml-6 after:hash opacity-0 group-hover:opacity-100 transition-all' href='#what-the-hell-is-consul' aria-label='Anchor'></a><span class='plain-code'>What the hell is Consul?</span></h3><div class="right-sidenote"><p>a “service” is whatever you say it is, but the classic example would be an HTTP micro-service server</p>
|
||
</div>
|
||
<p>Consul is a distributed database that attempts to be a source of truth for which services are currently running. It’s <a href='https://aphyr.com/posts/316-jepsen-etcd-and-consul' title=''>one of several</a> “service coordination” or “service discovery” databases; the other popular ones are <a href='https://etcd.io/' title=''>Etcd</a>, which once powered Kubernetes, and <a href='https://zookeeper.apache.org/' title=''>Zookeeper</a>, the original service coordinator, important in the Java/Hadoop ecosystem.</p>
|
||
|
||
<p>The challenge of these databases, the reason they’re not just trivial MySQL instances, is that you can’t just have one of them. Once you start relying on service discovery, it can’t go down, or your applications all break. So you end up with a cluster of databases, which have to agree with each other, even as services come and go. These systems all expend a lot of effort, and make a lot of compromises, in order to cough up consistent answers on flappy networks with fallible servers where individual components can fail.</p>
|
||
|
||
<p>How Consul works is that you have a cluster of “Consul Servers” — maybe 3, 5, or 7 — and then all the rest of your machines run a “Consul Agent” that talks to the Servers. The Servers execute the <a href='https://raft.github.io/' title=''>Raft consensus protocol</a>, maintaining a log of updates that form the basis for the database. Agents, in turn, inform the servers about events, such as an instance of a service terminating. An Agent can talk to any Server, but the Servers elect a leader, and updates are routed to the leader, which coordinates the Raft update to the log.</p>
|
||
|
||
<p>With me so far? Neither am I. But the specifics don’t matter much, as long as you understand that every machine in our fleet runs a lightweight Consul Agent that relays events to Consul Servers, which we only have a few of, locked in an unending and arcane ritual of consensus-tracking, producing: a map of every service running on <a href='http://Fly.io' title=''>Fly.io</a>, and exactly where it’s running. <a href='#other-consul-uses' title=''>Plus some other stuff</a>.</p>
|
||
|
||
<p>Let’s see it in action.</p>
|
||
<h3 id='consul-at-fly-io' class='group flex items-start whitespace-pre-wrap relative mt-14 sm:mt-16 mb-4 text-navy-950 font-heading'><a class='inline-block align-text-top relative top-[.15em] w-6 h-6 -ml-6 after:hash opacity-0 group-hover:opacity-100 transition-all' href='#consul-at-fly-io' aria-label='Anchor'></a><span class='plain-code'>Consul at Fly.io</span></h3>
|
||
<p>A Consul “service” at Fly.io, in the main, is an exposed port on an app a user deployed here. An “instance” of a service is a VM exposing that port. A “node” is one of Fly.io’s own servers.</p>
|
||
|
||
<p>We run a couple different kinds of servers, among them lightweight “edges” handling Internet traffic, and chonky “workers” running customer VMs. Both run <a href='https://fly.io/blog/the-tokio-1-x-upgrade/' title=''><code>fly-proxy</code>, our Rust+Tokio+Hyper proxy server</a>.</p>
|
||
|
||
<p>Every app running on <a href='http://Fly.io' title=''>Fly.io</a> gets a <a href='https://fly.io/blog/32-bit-real-estate/' title=''>unique, routable IPv4 address</a>.</p>
|
||
|
||
<p>That’s how our CDN works: we advertise these addresses, the same addresses, from dozens of data centers around the world, with BGP4 (this is “Anycast”). Backbone routing takes you to the closest one. Say <code>sandwich-bracket</code> is currently deployed in Frankfurt and Sydney. Anycast means the votes for doner land on a <a href='http://Fly.io' title=''>Fly.io</a> edge in Frankfurt, right next to a worker running <code>sandwich-bracket</code>; A bánh mì vote lands on a Sydney edge, and is routed to a Sydney worker. We’re not deployed in Tokyo, so a vote for egg salad hits a Tokyo edge, and gets routed… out of Japan.</p>
|
||
|
||
<p>The problem facing <code>fly-proxy</code> is, “where do I send this egg salad vote”. “The garbage” being, unfortunately, not a valid answer, <code>fly-proxy</code> needs to know which workers your <code>sandwich-bracket</code> app is running on, and then it needs to pick one to route to.</p>
|
||
|
||
<p>Here’s the data we’re working with:</p>
|
||
<div id="pricing-1"><div class="group relative min-w-0 bg-white shadow-md shadow-navy-500/10 rounded-xl mb-7 ring-1 ring-navy-300/40"><button type="button" class="bubble-wrap z-20 absolute right-2.5 top-2.5 text-transparent group-hover:text-navy-950 hocus:text-violet-600 bg-transparent group-hover:bg-white hocus:bg-violet-200/40 transition-colors grid place-items-center w-7 h-7 rounded-lg outline-none focus:outline-none" data-wrap-target="#table-qkji3n7k" data-wrap-type="nowrap"><svg class="w-5 h-5 pointer-events-none" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><g buffered-rendering="static"><path d="M11.912 10.037h2.732c1.277 0 2.315-.962 2.315-2.237a2.314 2.314 0 00-2.315-2.31H4.959M15.187 14.5H4.959M8.802 10H4.959"></path><path d="M13.081 8.466l-1.548 1.571 1.548 1.571"></path></g></svg><span class="bubble-sm bubble-tl [--offset-l:-9px] tail text-navy-950">Wrap text</span></button><div class="min-w-0 overflow-x-auto rounded-xl"><table class="table-stripe table-stretch table-pad text-sm whitespace-nowrap m-0" id="table-qkji3n7k"><thead class="text-navy-950 text-left"><tr>
|
||
<th>data</th>
|
||
<th>stability</th>
|
||
<th>what</th>
|
||
</tr>
|
||
</thead><tbody><tr>
|
||
<td>nodes</td>
|
||
<td>very stable</td>
|
||
<td>network locations of workers and edges</td>
|
||
</tr>
|
||
<tr>
|
||
<td>app IPs</td>
|
||
<td>stable</td>
|
||
<td>match incoming traffic to apps</td>
|
||
</tr>
|
||
<tr>
|
||
<td>services</td>
|
||
<td>changing</td>
|
||
<td>pinpoint instances to route to</td>
|
||
</tr>
|
||
<tr>
|
||
<td>health</td>
|
||
<td>flappy</td>
|
||
<td>pinpoint instances to avoid routing to</td>
|
||
</tr>
|
||
<tr>
|
||
<td>load</td>
|
||
<td>untenably flappy</td>
|
||
<td>enable load balancing</td>
|
||
</tr>
|
||
</tbody></table></div></div></div>
|
||
<p>Enter Consul. When you first created <code>sandwich-bracket</code> with our API, we:</p>
|
||
|
||
<ol>
|
||
<li>allocated an IPv4 address for it
|
||
</li><li>wrote it to Consul’s KV store
|
||
</li><li>deployed it to, say, a worker node in Frankfurt
|
||
</li><li>when that instance came up, our orchestration code registered the service instance with Consul.
|
||
</li></ol>
|
||
<div class="right-sidenote"><p><code>consul-templaterb</code> is <a href="https://medium.com/@pierresouchay" title="">Pierre Souchay’s</a> Ruby rewrite of <code>consul-template</code>, which comes with Consul. Track Consul, write a template, and then run a program that eats the file.</p>
|
||
</div>
|
||
<p>The simplest way to integrate all that information, and what we did until a couple months ago, is: we’d run <code>consul-templaterb</code> and ask it to track every service in Consul and sync a JSON file with the data; when the file is updated, <code>fly-proxy</code> gets a signal and re-reads it into memory.</p>
|
||
|
||
<p>Theoretically, Consul can tell us how “close” each of those services are <a href='https://fly.io/blog/building-clusters-with-serf/' title=''>– Consul puts a bunch of work into network telemetry</a> — but we do that bit ourselves, and so there’s another JSON file that <code>fly-proxy</code> watches to track network distance to every server in our fleet.</p>
|
||
<div class="right-sidenote"><p>Consul experts: avert your eyes</p>
|
||
</div>
|
||
<p>Consul doesn’t give us the load (in concurrent requests) on all the services. For a long time, we abused Consul for this, too: we tracked load in Consul KV. Never do this! Today, we use a messaging system to gossip load across our fleet.</p>
|
||
<div class="callout"><p>Specifically, we use <a href="https://nats.io/" title="">NATS</a>, a simple “brokered” asynchronous messaging system, the pretentious way to say “almost exactly like IRC, but for programs instead of people”.</p>
|
||
|
||
<p>Unlike Consul, NATS is neither consistent nor reliable. That’s what we like about it. We can get our heads around it. That’s a big deal: it’s easy to get billed for a lot of complexity by systems that solve problems 90% similar to yours. It seems like a win, but that 10% is murder. So our service discovery will likely never involve an event-streaming platform like Kafka.</p>
|
||
</div>
|
||
<p>Putting it all together, you have a sense of how our control plane works. Say the World Sandwich Authority declares doner is no longer a sandwich, and Japanese biochemists invent an even fluffier white bread. Traffic plummets in Frankfurt and skyrockets in Tokyo. We move our Frankfurt instance to Tokyo (<code>flyctl regions set syd nrt</code>). This kills the Frankfurt instance, and Frankfurt’s Consul Agent deregisters it. JSON files update across the fleet. The Tokyo instance comes up and gets registered; more JSON churn.</p>
|
||
|
||
<p><a name="other-consul-uses">We use Consul for other stuff!</a></p>
|
||
|
||
<ul>
|
||
<li>Apps on <a href='http://Fly.io' title=''>Fly.io</a> belong to “organizations”, and apps within an organization, all over the world, <a href='https://fly.io/blog/incoming-6pn-private-networks/' title=''>can talk to each other on 6PN private networks</a>. The DNS records for those 6PN addresses are derived (mostly) from Consul.
|
||
</li><li>One of Consul’s big features is “health checks” — it’ll report the health of a service based on configurable checks, so we don’t route traffic to instances that are having problems.
|
||
</li><li>Consul used to be <a href='https://fly.io/blog/our-user-mode-wireguard-year/' title=''>how we propagated WireGuard information for our users</a>, which is how <code>flyctl</code> works.
|
||
</li><li>Consul is also the source of truth for the WireGuard mesh network that links every machine in our fleet.
|
||
</li></ul>
|
||
<h3 id='it-burns' class='group flex items-start whitespace-pre-wrap relative mt-14 sm:mt-16 mb-4 text-navy-950 font-heading'><a class='inline-block align-text-top relative top-[.15em] w-6 h-6 -ml-6 after:hash opacity-0 group-hover:opacity-100 transition-all' href='#it-burns' aria-label='Anchor'></a><span class='plain-code'>It Burns</span></h3>
|
||
<p>It looks like textbook Consul. But it’s not, really.</p>
|
||
|
||
<p>Consul is designed to make it easy to manage a single engineering team’s applications. We’re managing deployments for thousands of teams. It’s led us to a somewhat dysfunctional relationship.</p>
|
||
|
||
<p>To start with, we have a single Consul namespace, and a single global Consul cluster. This seems nuts. You can federate Consul. But every Fly.io data center needs details for every app running on the planet! Federating costs us the global KV store. We can engineer around that, but then we might as well not use Consul at all.</p>
|
||
<div class="right-sidenote"><p>“Tracking” data in Consul generally involves <a href="https://www.consul.io/api-docs/features/blocking" title="">long-polling an HTTP endpoint</a>. Each HTTP request bears an index, which in turn tracks the Raft log; as a user, you don’t care about what this value means, only that if it changed, there’s new data. This is fine.</p>
|
||
</div>
|
||
<p>Consul’s API was also not designed with our needs in mind (nor should it have been). It’s got a reasonable API for tracking some things, but not quite the things we need. So, for instance, there’s an HTTP endpoint we can long-poll to <a href='https://www.consul.io/api-docs/catalog' title=''>track the catalog of services</a>. But:</p>
|
||
|
||
<ol>
|
||
<li>For any endpoint in the Consul HTTP API, if something changes, we get a refresh of all the data for that endpoint, which means incremental changes, which happen every few seconds, are expensive.
|
||
</li><li>What’s worse (and not Consul’s fault), tooling like <code>consul-templaterb</code> means we’re constantly rewriting and rereading large JSON files to register those small changes.
|
||
</li><li>The “<a href='https://www.consul.io/api-docs/catalog#list-services' title=''>catalog of services</a>” endpoint returns information about the services (the <code>sandwich-brackets</code> app), but not the metadata for individual instances of those services (the instances of <code>sandwich-brackets</code> in <code>nrt</code> and <code>syd</code>).
|
||
</li></ol>
|
||
|
||
<p>That second problem is kind of a nightmare. We have tens of thousands of distinct services. We need per-instance metadata for every instance of those services.</p>
|
||
|
||
<p>Consul can give us that metadata in two ways: by asking it about individual services, one-by-one, or by asking for service catalogs from each of our servers. We can’t long poll tens of thousands of endpoints. So, the way we get instance metadata from Consul is to ask it about servers, not services. We long-poll <a href='https://www.consul.io/api-docs/catalog#retrieve-map-of-services-for-a-node' title=''>an API endpoint for each individual server</a>. There’s no one endpoint that we can long-poll for all the nodes.</p>
|
||
<div class="callout"><p>You might at this point ask why we’re storing this kind of stuff in instance metadata at all. That’s a good question with a complicated answer. Some of it has to do with <a href="https://www.nomadproject.io/" title="">Nomad</a>, the orchestration service we use (and are gradually moving away from) to actually run VM jobs. Information about, say, what ports an app listens on percolates from a Nomad task description into its Consul service registration; that’s <a href="https://www.nomadproject.io/docs/integrations/consul-integration" title="">just how Nomad works.</a></p>
|
||
|
||
<p>You also can’t just factor the information out into, say, a Consul KV tree, because apps have versions, and different versions of apps listen on different ports, and <code>fly-proxy</code> needs to track them.</p>
|
||
|
||
<p>This stuff is all solvable! But, like, are you going to solve it by using Consul more carefully, or are you going to solve it by using Consul less?</p>
|
||
</div>
|
||
<p>Which is how it came to be that we found ourselves driving over 10 (t-e-n) gb/sec of Consul traffic across our fleet. Meanwhile, and I haven’t done the math, but it’s possible that the underlying data, carefully formatted and compressed, might fit on a dialup modem.</p>
|
||
|
||
<p>This, it turns out, was Not Entirely Our Fault. Long-suffering SRE Will Jordan, his brain shattered by ten gigabits of sustained Consul traffic, dove into the Consul codebase and <a href='https://github.com/hashicorp/consul/issues/12398' title=''>discovered a bug</a>: updates anywhere in Consul un-blocked every long-polling query. We had tens of thousands, N^2 (don’t email me!) in the number of nodes, all of which return a full refresh of the data they’re tracking when they unblock. Anyways, <a href='https://github.com/hashicorp/consul/pull/12399' title=''>Will wrote a couple dozen lines of Go,</a> and:</p>
|
||
|
||
<p><img alt="A gruesome bandwidth graph" src="/blog/a-foolish-consistency/assets/hashi-graph.webp?&centered" /></p>
|
||
<h2 id='extricating-ourselves' class='group flex items-start whitespace-pre-wrap relative mt-14 sm:mt-16 mb-4 text-navy-950 font-heading'><a class='inline-block align-text-top relative top-[.15em] w-6 h-6 -ml-6 after:hash opacity-0 group-hover:opacity-100 transition-all' href='#extricating-ourselves' aria-label='Anchor'></a><span class='plain-code'>Extricating Ourselves</span></h2>
|
||
<p>So, <code>consul-templaterb</code>is easy, but rough at the scale we work at. It runs Ruby code to to track updates that happen multiple times per second, each time writing giant JSON blobs to disk.</p>
|
||
<div class="right-sidenote"><p>One of Consul’s big-ticket features is a built-in DNS server. We don’t use it; we need our server to do silly stuff like <code>top3.nearest.of.my-app.internal</code>.</p>
|
||
</div>
|
||
<p>We felt this acutely with private DNS. Consul propagates the data that our DNS servers use (it’s similar to the data that <code>fly-proxy</code> uses). <a href='https://fly.io/blog/free-postgres/' title=''>Fly.io Postgres</a> depends on these DNS records, so it needs to work.</p>
|
||
|
||
<p>Our DNS server was originally written in Rust, and used <code>consul-templaterb</code> the way <code>fly-proxy</code> did, but wrote its updates to a sqlite database. At certain times, for certain workers, we’d experience double-digit second delays after instances came up — or worse, after they terminated. This is a big deal: it’s a window of many seconds during which internal requests get routed to nonexistent hosts; worse, the requests aren’t being handled by our smart proxy, but by people’s random app networking code.</p>
|
||
|
||
<p>We blamed Consul and <code>consul-templaterb</code>.</p>
|
||
|
||
<p>To fix this, we rewrote the DNS server (in Go), so that it tracked Consul directly, using Consul’s Go API, rather than relying on <code>consul-templaterb</code>. We also had it take “hints” directly from our orchestration code, via NATS messages, for instances starting and stopping.</p>
|
||
<div class="callout"><p>Rewriting a Rust program in Go is sacrilege, we know, but Go had the Consul libraries we needed, and, long term, that Go server is going to end up baked into our orchestration code, which is already in Go.</p>
|
||
</div>
|
||
<p>It turns out that what we really want (if not our dream Consul API) is a local sqlite cache of all of Consul’s state. That way our proxy, WireGuard code, DNS servers, and everything else can track updates across our fleet without a lot of complicated SRE work to make sure we’re interfacing with Consul properly.</p>
|
||
|
||
<p>By rewriting our DNS server, we’d inadvertently built most of that. So we extracted its Consul-tracking code and gave it an identity of its own, <code>attache</code>. <code>attache</code> runs on all our hosts and tracks most of Consul in sqlite. In theory, infra services at <a href='http://Fly.io' title=''>Fly.io</a> don’t need to know anything about Consul anymore, just the schema for that database.</p>
|
||
|
||
<p>New architectural possibilities are becoming apparent.</p>
|
||
|
||
<p>Take that horrible N^2 polling problem. Since we’ve abstracted Consul out, we really don’t need a better Consul API; we just need an <code>attache</code> API, so a “follower” <code>attache</code> can sync from a “leader”. Then we could run a small number of leaders around the world — maybe just alongside Consul Servers, so that almost all our Consul read traffic would be from machines local to the Consul Servers. We’d chain lots of followers from them, and possibly scale Consul indefinitely.</p>
|
||
|
||
<p>We can get clever about things, too. What we’d really be doing with “leader” and “follower” <code>attache</code> is replicating a sqlite database. That’s already a solved problem! There’s an amazing project called <a href='https://litestream.io/' title=''>Litestream</a> that <a href='https://litestream.io/how-it-works/' title=''>hooks</a> sqlite’s <a href='https://sqlite.org/wal.html' title=''>WAL checkpointing</a> process and <a href='https://litestream.io/how-it-works/' title=''>ships WAL frames to storage services</a>. Instead of building a new <code>attache</code> event streaming system, we could just set up “followers” to use Litestream to replicate the “leader” database.</p>
|
||
<figure class="post-cta">
|
||
<figcaption>
|
||
<h2>You don’t really have to think about any of this.</h2>
|
||
<p>It’s just a couple commands to get an app deployed on Fly.io; no service discovery required.</p>
|
||
<a class="btn btn-lg" href="https://fly.io/docs/speedrun/">
|
||
Try Fly for free <span class='opacity-50'>→</span>
|
||
</a>
|
||
</figcaption>
|
||
<div class="image-container">
|
||
<img src="/static/images/cta-turtle.webp" srcset="/static/images/cta-turtle@2x.webp 2x" alt="">
|
||
</div>
|
||
</figure>
|
||
|
||
<h3 id='we-dont-want-raft' class='group flex items-start whitespace-pre-wrap relative mt-14 sm:mt-16 mb-4 text-navy-950 font-heading'><a class='inline-block align-text-top relative top-[.15em] w-6 h-6 -ml-6 after:hash opacity-0 group-hover:opacity-100 transition-all' href='#we-dont-want-raft' aria-label='Anchor'></a><span class='plain-code'>We Don’t Want Raft</span></h3>
|
||
<p>We’re probably not going to do any of that, though, because we’re increasingly convinced that’s sinking engineering work into the wrong problem.</p>
|
||
|
||
<p>First, if you haven’t read the Google Research paper “<a href='https://research.google/pubs/pub40801/' title=''>The Tail At Scale</a>”, drop everything and remedy that. It’s amazing, an easy read, and influential at Fly.io.</p>
|
||
|
||
<p>Then: the problem we’re solving with <code>attache</code> is “creating a globally consistent map of all the apps running across our fleet”. But that’s not our real problem. Our real problem is “generate fast valid responses from incoming requests”. Solving the former problem is hard. It’s one answer to the real problem, but not necessarily the optimal one.</p>
|
||
|
||
<p>No matter how we synchronize service catalogs, we’re still beclowned by the speed of light. Our routing code always races our synchronization code. Routing in Tokyo is impacted by events happening in São Paolo (sandwich: mortadella on a roll), and events in São Paolo have a 260ms head start.</p>
|
||
|
||
<p>A different strategy for our real problem is request routing that’s resilient to variability. That means a distributing enough information to make smart first decisions, and smart routing to handle the stale data. We’ve already had to build some of that. For instance, if we route a request from an edge to a worker whose instances have died, <code>fly-proxy</code> replays it elsewhere.</p>
|
||
|
||
<p>You can finesse this stuff. “The Tail At Scale” discusses “hedged” requests, which are sometimes forwarded to multiple servers (after cleverly waiting for the 95th percentile latency); you take the first response. Google also uses “tied” requests, which fan out to multiple servers that can each call dibs, canceling the other handlers.</p>
|
||
|
||
<p>We’d do all of this stuff if we could. Google works on harder problems than we do, but they have an advantage: they own their applications. So, for instance, they can engineer their protocols to break large, highly-variable requests into smaller units of work, allowing them to interleave heavyweight tasks with latency-sensitive interactive ones to eliminate head-of-line blocking. We haven’t figured out how to do that with your Django POST and GET requests. But we’re working on it!</p>
|
||
|
||
<p>A lot of our problems are also just simpler than Raft makes them out to be. We used to use Consul to synchronize load information. But that’s kind of silly: Consul is slower than the feed of load events, and with events sourced globally, we never could have had a picture that was both fresh and accurate. What we needed were hints, not databases, and that’s what we have now: we use NATS (which isn’t necessarily even reliably delivered, let alone consensus-based) to gossip load.</p>
|
||
|
||
<p>Same goes for health checks. We already have to be resilient to stale health check information (it can and does change during request routing). Consul keeps a picture of health status, and we do still use it to restart ailing instances of apps and report status to our users. But <code>fly-proxy</code> doesn’t use it anymore, and shouldn’t: it does a fine job generating and gossiping health hints on its own.</p>
|
||
<h3 id='but-as-always-dns' class='group flex items-start whitespace-pre-wrap relative mt-14 sm:mt-16 mb-4 text-navy-950 font-heading'><a class='inline-block align-text-top relative top-[.15em] w-6 h-6 -ml-6 after:hash opacity-0 group-hover:opacity-100 transition-all' href='#but-as-always-dns' aria-label='Anchor'></a><span class='plain-code'>But, As Always: DNS</span></h3>
|
||
<p>We can make our routing resilient to stale health and load information, and push orchestration decisions closer to workers to be less reliant on distributed health events. We have a lot of flexibility with our own infrastructure.</p>
|
||
|
||
<p>That flexibility stops at the doors of the VM running your Django app. We don’t own your app; we don’t really even know what it does. We’re <a href='https://christoph.luppri.ch/fixing-dns-resolution-for-ruby-on-alpine-linux' title=''>at the mercy of your socket code.</a></p>
|
||
|
||
<p>So one place we’re kind of stuck with Consul-style strongly consistent service maps is DNS. Normal apps simply aren’t built to assume that DNS can be a moving target. If your app looks up <code>sandwich-postgres.internal</code>, it needs to get a valid address; if it gets nothing, or, worse, the address of a VM that terminated 750ms ago, it’ll probably break, and break in hyper-annoying ways that we don’t yet have clever ways to detect.</p>
|
||
|
||
<p>We’ve spent the better part of 9 months improving the performance of our <code>.internal</code> DNS, which is a lot for a feature that was an afterthought when I threw it together. We’re in a sane place right now, but we can’t stay here forever.</p>
|
||
|
||
<p>What we’re going to do instead – you’ll see it soon on our platform – is play the ultimate CS trump card, and <code>add another layer of indirection</code>. Apps on Fly.io are getting, in addition to the DNS names they have today, “internal Anycast”: a stable address that routes over <code>fly-proxy</code>, so we can use the same routing smarts we’re using for Internet traffic for Postgres and Redis.</p>
|
||
|
||
<p>You’ll still get to be fussy about connectivity between your internal apps! Internal Anycast is optional. But it’s where our heads are at with making internal connectivity resilient and efficient.</p>
|
||
<h2 id='and-so' class='group flex items-start whitespace-pre-wrap relative mt-14 sm:mt-16 mb-4 text-navy-950 font-heading'><a class='inline-block align-text-top relative top-[.15em] w-6 h-6 -ml-6 after:hash opacity-0 group-hover:opacity-100 transition-all' href='#and-so' aria-label='Anchor'></a><span class='plain-code'>And So</span></h2>
|
||
<p>We mostly like Consul and would use it again in new designs. It’s easy to stand up. It’s incredibly useful to deploy infrastructure configurations. For example: we write blog posts like this and people invariably comment about how cool it is that we have a WireGuard mesh network between all of our machines. But, not to diminish Steve’s work on flywire, that system falls straight out of us using Consul. It’s great!</p>
|
||
|
||
<p>But we probably wouldn’t use Consul as the backing store for a global app platform again, in part because a global app platform might not even want a single globally consistent backing store. Our trajectory is away from it.</p>
|
||
|
||
<footer class="flex items-center flex-wrap col-span-full w-full max-w-[44rem] mx-auto mt-14 md:mt-24 mb-4 text-gray-400">
|
||
<dl class="flex items-center text-xs font-bold uppercase tracking-wider">
|
||
<dt>
|
||
Last updated
|
||
</dt>
|
||
<span class="mx-2 text-gray-300" aria-hidden>•</span>
|
||
<dd>
|
||
<time datetime="2022-03-29">
|
||
Mar 29, 2022
|
||
</time>
|
||
</dd>
|
||
</dl>
|
||
<span class="flex-1 bg-gray-100 flex-1 h-px mx-2"></span>
|
||
<a
|
||
class="flex items-center justify-center w-7 h-7 hover:text-blue-500 transition-colors"
|
||
href="https://twitter.com/share?text=A Foolish Consistency: Consul at Fly.io&url=https://fly.io/blog/a-foolish-consistency/&via=flydotio"
|
||
target="_blank"
|
||
>
|
||
|
||
<svg role="img" class="" viewBox="0 0 24 24" style="pointer-events: none; width: 18px; height: 18px;" fill="currentColor">
|
||
<g buffered-rendering="static">
|
||
<path d="M22.208 3.871c-.757.252-1.824.496-2.834.748-.757-.883-1.892-1.388-3.154-1.388-2.902 0-4.92 2.649-4.289 5.425-3.659-.126-6.939-1.892-9.083-4.542-1.135 1.892-.505 4.542 1.388 5.803-.757 0-1.388-.126-2.019-.505 0 2.145 1.388 4.037 3.532 4.416-.631.252-1.388.252-2.019.126.505 1.766 2.145 3.028 4.037 3.028-1.892 1.388-4.289 2.019-6.56 1.766 1.892 1.262 4.163 2.019 6.686 2.019 8.2 0 12.742-6.813 12.49-12.994.753-1.089 1.49-2.201 1.824-3.902z" />
|
||
</g>
|
||
</svg>
|
||
<span class="sr-only">Share this post on Twitter</span>
|
||
</a>
|
||
<a
|
||
class="flex items-center justify-center w-7 h-7 hover:text-orange-500 transition-colors"
|
||
href="http://news.ycombinator.com/submitlink?u=https://fly.io/blog/a-foolish-consistency/&t=A Foolish Consistency: Consul at Fly.io"
|
||
target="_blank"
|
||
>
|
||
|
||
<svg role="img" class="" viewBox="0 0 24 24" style="pointer-events: none; width: 14px; height: 14px;" fill="currentColor">
|
||
<g buffered-rendering="static">
|
||
<path d="M16.063 2h4.75l-6.625 12.5v7.5h-4.126l.001-7.5-6.875-12.5h4.875l4.125 8.75 3.875-8.75z" />
|
||
</g>
|
||
</svg>
|
||
<span class="sr-only">Share this post on Hacker News</span>
|
||
</a>
|
||
<a
|
||
class="flex items-center justify-center w-7 h-7 hover:text-red-500 transition-colors"
|
||
href="http://www.reddit.com/submit?url=https://fly.io/blog/a-foolish-consistency/&title=A Foolish Consistency: Consul at Fly.io"
|
||
target="_blank"
|
||
>
|
||
|
||
<svg role="img" class="" viewBox="0 0 24 24" style="pointer-events: none; width: 20px; height: 20px;" fill="currentColor">
|
||
<g buffered-rendering="static">
|
||
<path d="M15.029 14.708c-.762 0-1.401-.616-1.401-1.377 0-.762.639-1.4 1.401-1.4s1.378.638 1.378 1.4c0 .761-.616 1.377-1.378 1.377m.194 2.546c-.674.673-1.727 1-3.224 1-1.496 0-2.551-.327-3.223-1-.07-.07-.11-.165-.11-.264 0-.205.169-.374.374-.374.099 0 .194.04.265.11.524.525 1.406.781 2.694.781s2.17-.256 2.696-.781c.07-.07.165-.109.264-.109.205 0 .373.168.373.373 0 .099-.039.194-.109.264m-7.631-3.923c0-.762.639-1.4 1.4-1.4.76 0 1.377.638 1.377 1.4 0 .76-.616 1.377-1.377 1.377-.762 0-1.4-.617-1.4-1.377m14.408-1.515c-.002-1.242-1.023-2.264-2.265-2.265-.569-.002-1.118.213-1.535.6-1.495-.974-3.497-1.602-5.714-1.688l1.223-3.734 3.213.757c.002 1.022.842 1.861 1.864 1.862 1.022-.001 1.863-.842 1.865-1.864-.002-1.023-.843-1.864-1.865-1.865-.746 0-1.423.448-1.716 1.134l-3.52-.828-.008-.002-.33-.078-1.51 4.61c-2.301.043-4.386.669-5.937 1.664-.411-.364-.943-.568-1.501-.568-1.241.001-2.262 1.023-2.264 2.264 0 .786.408 1.517 1.076 1.929-.038.221-.057.445-.057.673 0 3.288 4.01 5.964 8.939 5.964s8.94-2.676 8.94-5.964c0-.212-.016-.422-.049-.629.713-.398 1.155-1.155 1.151-1.972" />
|
||
</g>
|
||
</svg>
|
||
<span class="sr-only">Share this post on Reddit</span>
|
||
</a>
|
||
<div class="xl:hidden sm:block w-full text-base font-medium">
|
||
<dl class="pt-12 pb-16 border-b border-gray-100 grid gap-5">
|
||
<dt class="sr-only">Author</dt>
|
||
<dd class="flex items-center space-x-6">
|
||
<img alt="Thomas Ptacek" class="w-16 h-16 object-cover rounded-xl" src="/static/images/thomas.webp" />
|
||
<dl class="leading-5 whitespace-no-wrap">
|
||
<dt class="sr-only">Name</dt>
|
||
<dd class="text-navy-900">
|
||
Thomas Ptacek
|
||
</dd>
|
||
<dt class="sr-only">@tqbf</dt>
|
||
<dd>
|
||
<a href="https://twitter.com/tqbf" class="text-violet-500 hover:text-violet-700 transition-colors">
|
||
@tqbf
|
||
</a>
|
||
</dd>
|
||
</dl>
|
||
</dd>
|
||
</dl>
|
||
<dl class="pt-12">
|
||
<dt class="text-navy-900 mb-1">
|
||
Next post ↑
|
||
</dt>
|
||
<dd class="mb-7">
|
||
<a class="line-clamp-2 text-violet-500 hover:text-violet-700 transition-colors" href="/blog/logbook-2022-04-20/">
|
||
Logbook - 2022-04-20
|
||
</a>
|
||
</dd>
|
||
<dt class="text-navy-900 mb-1">
|
||
Previous post ↓
|
||
</dt>
|
||
<dd>
|
||
<a class="line-clamp-2 text-violet-500 hover:text-violet-700 transition-colors" href="/blog/intro-to-accessibility/">
|
||
Accessibility for real-time web apps
|
||
</a>
|
||
</dd>
|
||
</dl>
|
||
</div>
|
||
</footer>
|
||
</section>
|
||
<dl class="text-sm w-44 ml-8 relative top-[-5.85rem] font-medium hidden xl:block">
|
||
<dt class="text-navy-900 mb-1">
|
||
Next post ↑
|
||
</dt>
|
||
<dd class="mb-7">
|
||
<a class="line-clamp-2 text-violet-500 hover:text-violet-700 transition-colors" href="/blog/logbook-2022-04-20/">
|
||
Logbook - 2022-04-20
|
||
</a>
|
||
</dd>
|
||
<dt class="text-navy-900 mb-1">
|
||
Previous post ↓
|
||
</dt>
|
||
<dd>
|
||
<a class="line-clamp-2 text-violet-500 hover:text-violet-700 transition-colors" href="/blog/intro-to-accessibility/">
|
||
Accessibility for real-time web apps
|
||
</a>
|
||
</dd>
|
||
</dl>
|
||
</article>
|
||
</main>
|
||
|
||
|
||
<footer
|
||
class="text-sm text-gray-400 leading-6 pb-8 pt-12 lg:pt-20 text-medium bg-gray-100 text-gray-500"
|
||
role="contentinfo"
|
||
>
|
||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 pb-12 lg:pb-20 grid md:grid-cols-auto-span items-start gap-10 md:gap-16">
|
||
<a href="/" class="justify-self-start">
|
||
|
||
<svg
|
||
role="img"
|
||
class="text-navy-900"
|
||
fill-rule="evenodd"
|
||
viewBox="0 0 259 84"
|
||
style="pointer-events: none; width: auto; height: 36px;"
|
||
aria-labelledby="logo-title-4020 logo-description-4020"
|
||
>
|
||
<title id="logo-title-4020">Fly</title>
|
||
<desc id="logo-description-4020">App performance optimization</desc>
|
||
<g buffered-rendering="static">
|
||
<path
|
||
d="M57.413 10.134h9.454c8.409 0 15.236 6.827 15.236 15.236v33.243c0 8.409-6.827 15.236-15.236 15.236h-.745c-4.328-.677-6.205-1.975-7.655-3.072l-12.02-9.883a1.692 1.692 0 0 0-2.128 0l-3.905 3.211-10.998-9.043a1.688 1.688 0 0 0-2.127 0L12.01 68.503c-3.075 2.501-5.109 2.039-6.428 1.894C2.175 67.601 0 63.359 0 58.613V25.37c0-8.409 6.827-15.236 15.237-15.236h9.433l-.017.038-.318.927-.099.318-.428 1.899-.059.333-.188 1.902-.025.522-.004.183.018.872.043.511.106.8.135.72.16.663.208.718.54 1.52.178.456.94 1.986.332.61 1.087 1.866.416.673 1.517 2.234.219.296 1.974 2.569.638.791 2.254 2.635.463.507 1.858 1.999.736.762 1.216 1.208-.244.204-.152.137c-.413.385-.805.794-1.172 1.224a10.42 10.42 0 0 0-.504.644 8.319 8.319 0 0 0-.651 1.064 6.234 6.234 0 0 0-.261.591 5.47 5.47 0 0 0-.353 1.606l-.007.475a5.64 5.64 0 0 0 .403 1.953 5.44 5.44 0 0 0 1.086 1.703c.338.36.723.674 1.145.932.359.22.742.401 1.14.539a6.39 6.39 0 0 0 2.692.306h.005a6.072 6.072 0 0 0 2.22-.659c.298-.158.582-.341.848-.549a5.438 5.438 0 0 0 1.71-2.274c.28-.699.417-1.446.405-2.198l-.022-.393a5.535 5.535 0 0 0-.368-1.513 6.284 6.284 0 0 0-.285-.618 8.49 8.49 0 0 0-.67-1.061 11.022 11.022 0 0 0-.354-.453 14.594 14.594 0 0 0-1.308-1.37l-.329-.28.557-.55 2.394-2.5.828-.909 1.287-1.448.837-.979 1.194-1.454.808-1.016 1.187-1.587.599-.821.85-1.271.708-1.083 1.334-2.323.763-1.524.022-.047.584-1.414a.531.531 0 0 0 .02-.056l.629-1.962.066-.286.273-1.562.053-.423.016-.259.019-.978-.005-.182-.05-.876-.062-.68-.31-1.961c-.005-.026-.01-.052-.018-.078l-.398-1.45-.137-.403-.179-.446Zm4.494 41.455a3.662 3.662 0 0 0-3.61 3.61 3.663 3.663 0 0 0 3.61 3.609 3.665 3.665 0 0 0 3.611-3.609 3.663 3.663 0 0 0-3.611-3.61Z"
|
||
fill="url(#default-radial)" fill-opacity="1"
|
||
/>
|
||
<path
|
||
d="M35.639 72.544l-.637.535a3.332 3.332 0 01-2.09.762H15.235a15.176 15.176 0 01-9.654-3.451c1.319.145 3.353.607 6.428-1.894l15.277-13.44a1.693 1.693 0 012.127 0l10.997 9.042 3.904-3.21c.619-.5 1.51-.5 2.128 0l12.019 9.882c1.45 1.097 3.327 2.394 7.654 3.071H58.12a3.394 3.394 0 01-1.963-.654l-.14-.108-.593-.493a1.247 1.247 0 00-.158-.159c-.672-.563-9.187-7.617-9.187-7.617a1 1 0 00-1.281.002s.021.026-9.038 7.615a1.12 1.12 0 00-.121.117zm26.262-20.96a3.678 3.678 0 00-3.61 3.609 3.68 3.68 0 003.61 3.609 3.68 3.68 0 003.61-3.609 3.678 3.678 0 00-3.61-3.609zM38.566 40.648L37.35 39.44l-.736-.762-1.858-1.999-.463-.507-2.253-2.634-.638-.791-1.974-2.569-.219-.296-1.517-2.234-.416-.673-1.087-1.866-.332-.61-.94-1.985-.178-.456-.539-1.52-.208-.718-.16-.663-.135-.72-.106-.8-.043-.511-.018-.872.004-.183.025-.522.188-1.901.059-.333.428-1.899.098-.318.318-.927.102-.24.506-1.112.351-.662.489-.806.487-.718.347-.456.4-.482.44-.484.377-.378.918-.808.671-.549c.016-.014.033-.026.05-.038l.794-.537.631-.402 1.198-.631c.018-.011.039-.02.058-.029l1.698-.705.157-.059 1.51-.442.638-.143.862-.173.572-.087.877-.109.598-.053 1.187-.063.465-.005.881.018.229.013 1.276.106 1.687.238.195.041 1.668.415.49.146.544.188.663.251.524.222.77.363.485.249.872.512.325.2 1.189.868.341.296.828.754.041.041.703.754.242.273.825 1.096.168.262.655 1.106.197.379.369.825.386.963.137.403.398 1.45a.89.89 0 01.018.078l.31 1.961.062.679.05.876.005.182-.019.978-.016.259-.053.423-.273 1.562-.066.286-.629 1.962a.626.626 0 01-.02.056l-.584 1.414-.022.047-.763 1.523-1.334 2.323-.708 1.083-.849 1.271-.599.821-1.187 1.587-.808 1.016-1.194 1.453-.837.979-1.287 1.448-.828.909-2.394 2.5-.556.55.328.28c.465.428.902.885 1.308 1.37.122.148.24.299.354.453.249.336.473.691.67 1.06.106.2.201.407.285.618.191.484.32.996.368 1.513l.022.393c.012.752-.125 1.5-.405 2.198a5.438 5.438 0 01-1.71 2.274c-.266.208-.55.391-.848.549a6.08 6.08 0 01-2.219.659h-.005a6.403 6.403 0 01-2.692-.306 5.882 5.882 0 01-1.14-.539 5.523 5.523 0 01-1.145-.932 5.458 5.458 0 01-1.086-1.703 5.662 5.662 0 01-.403-1.953l.007-.475a5.47 5.47 0 01.353-1.606c.077-.202.164-.399.261-.591.19-.37.408-.725.651-1.063.159-.221.328-.436.504-.644.367-.43.759-.839 1.172-1.224l.152-.137.244-.204z"
|
||
fill="currentColor"
|
||
/>
|
||
<path
|
||
d="M35.002 73.079l9.796-8.267a1 1 0 011.281-.002l9.938 8.269c.604.492 1.36.761 2.139.762h-25.28c.776 0 1.527-.269 2.126-.762zM41.1 43.568l.096.028c.031.015.057.036.085.055l.08.071c.198.182.39.373.575.569.13.139.257.282.379.43.155.187.3.383.432.587.057.09.11.181.16.276.043.082.082.167.116.253.06.15.105.308.119.469l-.003.302a1.726 1.726 0 01-.817 1.343 2.333 2.333 0 01-.994.327l-.373.011-.315-.028a2.398 2.398 0 01-.433-.105 2.07 2.07 0 01-.41-.192l-.246-.18a1.685 1.685 0 01-.56-.96 2.418 2.418 0 01-.029-.19l-.009-.288c.005-.078.017-.155.034-.232.043-.168.105-.331.183-.486.101-.194.216-.381.344-.559.213-.288.444-.562.691-.821.159-.168.322-.331.492-.488l.121-.109c.084-.055.085-.055.181-.083h.101zM40.481 3.42l.039-.003v33.665l-.084-.155a94.101 94.101 0 01-3.093-6.267 67.257 67.257 0 01-2.099-5.255 41.665 41.665 0 01-1.265-4.326c-.265-1.163-.469-2.343-.553-3.535a16.923 16.923 0 01-.029-1.528c.008-.444.026-.887.054-1.33.044-.696.115-1.391.217-2.081.081-.543.181-1.084.304-1.619.098-.425.212-.847.342-1.262.188-.6.413-1.186.675-1.758.096-.206.199-.411.307-.612.65-1.204 1.532-2.313 2.687-3.054a5.609 5.609 0 012.498-.88zm4.365.085l2.265.646c1.049.387 2.059.891 2.987 1.521a11.984 11.984 0 013.212 3.204c.502.748.918 1.555 1.243 2.398.471 1.247.763 2.554.866 3.882.03.348.047.697.054 1.046.008.324.006.649-.02.973-.064.725-.2 1.442-.407 2.14a17.03 17.03 0 01-.587 1.684c-.28.685-.591 1.357-.932 2.013-.754 1.457-1.623 2.852-2.553 4.201a65.451 65.451 0 01-3.683 4.806 91.02 91.02 0 01-4.417 4.896 93.66 93.66 0 002.907-5.949c.5-1.124.971-2.26 1.414-3.407.487-1.26.927-2.537 1.317-3.83.29-.969.546-1.948.757-2.938.181-.849.323-1.707.411-2.57.074-.72.101-1.444.083-2.166a30.867 30.867 0 00-.049-1.325c-.106-1.775-.376-3.545-.894-5.248a15.341 15.341 0 00-.714-1.892c-.663-1.444-1.588-2.793-2.84-3.778l-.42-.307z"
|
||
fill="#fff"
|
||
/>
|
||
<path
|
||
d="M179.213 64.297l-10.751-23.015c-.898-1.917-1.433-2.618-2.331-3.431l-.874-.788c-.697-.676-1.155-1.302-1.155-2.045 0-1.064.843-1.96 2.378-1.96h9.334c1.465 0 2.378.762 2.378 1.9 0 .635-.292 1.111-.661 1.578-.438.555-1.008 1.096-1.008 2.082 0 .618.18 1.234.527 2.021l6.416 15.025 5.755-14.647c.354-.974.596-1.832.596-2.519 0-1.069-.581-1.505-1.029-1.983-.39-.415-.702-.854-.702-1.557 0-1.149.935-1.9 2.193-1.9h5.748c1.612 0 2.378.834 2.378 1.9 0 .682-.393 1.314-1.166 1.996l-.813.668c-1.132.925-1.656 2.263-2.251 3.647l-8.716 20.998c-1.03 2.455-2.563 5.863-4.905 8.659-2.379 2.84-5.587 5.048-9.932 5.048-3.638 0-5.84-1.737-5.84-4.24 0-2.293 1.696-4.12 3.924-4.12 1.22 0 1.855.576 2.499 1.169.532.489 1.072.991 2.137.991.988 0 1.908-.418 2.742-1.093 1.274-1.03 2.341-2.652 3.129-4.384zm63.175-.082c4.839 0 8.804-1.658 11.897-4.967 3.09-3.304 4.636-7.281 4.636-11.931 0-4.539-1.469-8.268-4.396-11.191-2.926-2.921-6.723-4.388-11.396-4.388-4.92 0-8.944 1.597-12.077 4.78-3.135 3.186-4.703 7.045-4.703 11.578 0 4.493 1.496 8.301 4.483 11.425 2.99 3.126 6.84 4.694 11.556 4.694zm-40.921-.36c2.798 0 4.788-1.884 4.788-4.6 0-2.652-2.055-4.54-4.788-4.54-2.863 0-4.912 1.891-4.912 4.54 0 2.713 2.05 4.6 4.912 4.6zm9.964-4.305l.681-.72c.81-.787 1.071-1.582 1.071-3.774V42.097c0-1.895-.258-2.741-1.062-3.465l-.801-.718c-.785-.693-1.043-1.124-1.043-1.816 0-.984.763-1.791 1.99-2.071l5.44-1.32c.52-.126 1.107-.249 1.562-.249.626 0 1.138.206 1.497.563.36.358.572.873.572 1.517v20.518c0 2.069.251 3.031 1.115 3.758a.359.359 0 01.039.039l.608.708c.764.743 1.081 1.236 1.081 1.914 0 1.209-.912 1.9-2.377 1.9h-9.211c-1.396 0-2.316-.687-2.316-1.9 0-.681.317-1.178 1.154-1.925zm-61.567.001l.681-.721c.811-.787 1.071-1.582 1.071-3.774V27.999c0-1.835-.194-2.736-1.053-3.459l-.822-.796c-.709-.689-.968-1.116-.968-1.805 0-.985.767-1.789 1.927-2.07l5.378-1.32c.521-.126 1.107-.249 1.563-.249.621 0 1.147.187 1.522.542.376.356.608.885.608 1.598v34.616c0 2.074.258 2.981 1.125 3.766l.694.734c.769.748 1.025 1.238 1.025 1.919 0 .502-.153.907-.426 1.216-.385.435-1.03.684-1.89.684h-9.21c-.86 0-1.505-.249-1.891-.684-.272-.309-.425-.714-.425-1.216 0-.682.253-1.176 1.091-1.924zm-25.079-13.934v9.319c0 1.404.278 2.701 1.435 3.768l.748.726c.838.813 1.093 1.3 1.093 2.045 0 1.138-.913 1.9-2.378 1.9h-10.385c-1.465 0-2.377-.762-2.377-1.9 0-.884.259-1.303 1.097-2.049l.745-.724c.868-.786 1.434-1.857 1.434-3.766V30.039c0-1.517-.336-2.758-1.435-3.769l-.749-.726c-.77-.747-1.092-1.238-1.092-1.985 0-1.206.915-1.96 2.377-1.96h27.817c1.063 0 1.997.237 2.594.822.415.407.68.981.71 1.778l.433 6.421c.043.803-.194 1.472-.657 1.885-.319.284-.748.454-1.288.454-.681 0-1.203-.257-1.669-.701-.419-.399-.792-.959-1.213-1.618-1.016-1.624-1.489-2.208-2.572-2.967-1.507-1.112-3.803-1.494-8.145-1.494-2.505 0-4.086.109-5.082.366-.644.166-1.016.382-1.215.699-.204.324-.226.734-.226 1.235v12.618h6.523c1.561 0 2.659-.282 3.931-2.021l.007-.01c.51-.649.879-1.127 1.23-1.444.409-.37.802-.545 1.323-.545a1.9 1.9 0 011.883 1.901v8.699c0 1.165-.908 1.96-1.883 1.96-.485 0-.879-.173-1.289-.535-.353-.31-.723-.775-1.203-1.396-1.392-1.802-2.375-2.089-3.999-2.089h-6.523zm110.214-.22c0-3.121.68-5.364 2.089-6.713 1.392-1.332 2.888-2.006 4.496-2.006 2.212 0 4.205 1.238 6.003 3.672 1.837 2.489 2.746 5.853 2.746 10.086 0 3.124-.682 5.388-2.093 6.776-1.391 1.369-2.886 2.063-4.493 2.063-2.212 0-4.204-1.248-6.002-3.701-1.838-2.51-2.746-5.904-2.746-10.177zm-18.202-16.878c2.804 0 4.788-1.578 4.788-4.3 0-2.658-1.982-4.24-4.788-4.24-2.871 0-4.851 1.583-4.851 4.24 0 2.656 1.981 4.3 4.851 4.3z"
|
||
fill="currentColor"
|
||
/>
|
||
</g>
|
||
<defs>
|
||
<radialGradient id="default-radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.593 41.714) scale(59.4764)">
|
||
<stop offset="0" stop-color="#ba7bf0" />
|
||
<stop offset=".45" stop-color="#996bec" />
|
||
<stop offset="1" stop-color="#5046e4" />
|
||
</radialGradient>
|
||
<radialGradient id="laravel-bytes-radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.593 41.714) scale(59.4764)">
|
||
<stop offset="0" stop-color="#97f6e4" />
|
||
<stop offset=".45" stop-color="#5cead4" />
|
||
<stop offset="1" stop-color="#0d9488" />
|
||
</radialGradient>
|
||
</defs>
|
||
</svg>
|
||
</a>
|
||
<div class="grid grid-cols-fit-24 gap-10 items-start lg:justify-items-center">
|
||
<dl>
|
||
<dt class="font-bold uppercase tracking-wider text-xs text-navy-900 mb-3">Company</dt>
|
||
<dd class="font-medium flex flex-col items-start">
|
||
<a href="/about/" class="hover:text-violet-600 transition-colors">About</a>
|
||
<a href="/pricing/" class="hover:text-violet-600 transition-colors">Pricing</a>
|
||
<a href="/jobs/" class="hover:text-violet-600 transition-colors">Jobs</a>
|
||
<a href="/news/" class="hover:text-violet-600 transition-colors">News</a>
|
||
</dd>
|
||
</dl>
|
||
<dl>
|
||
<dt class="font-bold uppercase tracking-wider text-xs text-navy-900 mb-3">Articles</dt>
|
||
<dd class="font-medium flex flex-col items-start">
|
||
<a href="/blog/" class="hover:text-violet-600 transition-colors">Blog</a>
|
||
<a href="/infra-log/" class="hover:text-violet-600 transition-colors">Infra Log</a>
|
||
</dd>
|
||
</dl>
|
||
<dl>
|
||
<dt class="font-bold uppercase tracking-wider text-xs text-navy-900 mb-3">Resources</dt>
|
||
<dd class="font-medium flex flex-col items-start">
|
||
<a href="/docs/" class="hover:text-violet-600 transition-colors">Docs</a>
|
||
<a href="/docs/support/" class="hover:text-violet-600 transition-colors">Support</a>
|
||
<a href="/support/" class="hover:text-violet-600 transition-colors">Support Metrics</a>
|
||
<a href="https://status.flyio.net/" class="hover:text-violet-600 transition-colors">Status</a>
|
||
</dd>
|
||
</dl>
|
||
<dl>
|
||
<dt class="font-bold uppercase tracking-wider text-xs text-navy-900 mb-3">Contact</dt>
|
||
<dd class="font-medium flex flex-col items-start">
|
||
<a href="https://github.com/superfly/" class="hover:text-violet-600 transition-colors">GitHub</a>
|
||
<a href="https://twitter.com/flydotio" class="hover:text-violet-600 transition-colors">Twitter</a>
|
||
<a href="https://community.fly.io/" class="hover:text-violet-600 transition-colors">Community</a>
|
||
</dd>
|
||
</dl>
|
||
<dl>
|
||
<dt class="font-bold uppercase tracking-wider text-xs text-navy-900 mb-3">Legal</dt>
|
||
<dd class="font-medium flex flex-col items-start">
|
||
<a href="/docs/security/" class="hover:text-violet-600 transition-colors">Security</a>
|
||
<a href="/legal/privacy-policy" class="hover:text-violet-600 transition-colors">Privacy policy</a>
|
||
<a href="/legal/terms-of-service" class="hover:text-violet-600 transition-colors">Terms of service</a>
|
||
<a href="/legal/acceptable-use-policy" class="hover:text-violet-600 transition-colors">Acceptable Use Policy</a>
|
||
<button id="footer-cookie-prefs" type="button" hidden class="hover:text-violet-600 text-left transition-colors">Cookie preferences</button>
|
||
</dd>
|
||
</dl>
|
||
</div>
|
||
</div>
|
||
<p class="text-xs text-center mb-0">Copyright © 2026 Fly.io</p>
|
||
</footer>
|
||
|
||
|
||
<script src="/static/javascripts/application.js"></script>
|
||
</body>
|
||
|
||
|
||
</html> |