
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Wed, 15 Apr 2026 15:11:05 GMT</lastBuildDate>
        <item>
            <title><![CDATA[A Question of Timing]]></title>
            <link>https://blog.cloudflare.com/a-question-of-timing/</link>
            <pubDate>Wed, 17 Oct 2018 12:00:00 GMT</pubDate>
            <description><![CDATA[ When considering website performance, the term TTFB - time to first byte - crops up regularly. Often we see measurements from cURL and Chrome, and this article will show what timings those tools can produce, including time to first byte... ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3zCGPwzpCVzjoRBJnEigP6/7cf0708f61d20f3ce699bf43fa9987a1/photo-1501139083538-0139583c060f" />
            
            </figure><p><i>Photo by </i><a href="https://unsplash.com/@aronunsplash?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"><i>Aron</i></a><i> / </i><a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"><i>Unsplash</i></a></p><p>When considering website performance, the term TTFB - time to first byte - crops up regularly. Often we see measurements from cURL and Chrome, and this article will show what timings those tools can produce, including time to first byte, and discuss whether this is the measurement you are really looking for.</p>
    <div>
      <h3>Timing with cURL</h3>
      <a href="#timing-with-curl">
        
      </a>
    </div>
    <p><a href="https://curl.haxx.se/">cURL</a> is an excellent tool for debugging web requests, and it includes the ability to take timing measurements. Let’s take an example website <a href="http://www.zasag.mn">www.zasag.mn</a> (the Mongolian government), and measure how long a request to its home page takes:</p><p>First configure the output format for cURL in <code>~/.curlrc</code>:</p>
            <pre><code>$ cat .curlrc
-w "dnslookup: %{time_namelookup} | connect: %{time_connect} | appconnect: %{time_appconnect} | pretransfer: %{time_pretransfer} | starttransfer: %{time_starttransfer} | total: %{time_total} | size: %{size_download}\n"</code></pre>
            <p>Now connect to the site dropping the output (<code>-o /dev/null</code>) since we’re only interested in the timing:</p>
            <pre><code>$ curl -so /dev/null https://www.zasag.mn
dnslookup: 1.510 | connect: 1.757 | appconnect: 2.256 | pretransfer: 2.259 | 
starttransfer: 2.506 | total: 3.001 | size: 53107</code></pre>
            <p>These timings are in seconds. Depending on your version of cURL, you may get more decimal places than this example. 3 seconds is a long time, and remember this is only for the HTML from the home page - it doesn’t include any JavaScript, images, etc.</p><p>The diagram below shows what each of those timings refer to against a typical HTTP over TLS 1.2 connection (TLS 1.3 setup <a href="/tls-1-3-overview-and-q-and-a/">needs one less round trip</a>):</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2EfInkqn7sNtWkWFdxPDk4/2f3e1c0202ed6025bbe12f6f540c1b4a/Screen-Shot-2018-10-16-at-14.51.29-1.png" />
            
            </figure><ul><li><p><b>time_namelookup</b> in this example takes a long time. To exclude DNS resolver performance from the figures, you can resolve the IP for cURL: <code>--resolve www.zasag.mn:443:218.100.84.167</code>. It may also be worth looking for a <a href="https://www.dnsperf.com/#!dns-resolvers">faster</a> <a href="https://1.1.1.1/">resolver</a> :).</p></li><li><p><b>time_connect</b> is the TCP three-way handshake from the client’s perspective. It ends just after the client sends the ACK - it doesn't include the time taken for that ACK to reach the server. It should be close to the <a href="https://www.cloudflare.com/learning/cdn/glossary/round-trip-time-rtt/">round-trip time (RTT)</a> to the server. In this example, RTT looks to be about 200 ms.</p></li><li><p><b>time_appconnect</b> here is TLS setup. The client is then ready to send it’s HTTP GET request.</p></li><li><p><b>time_starttransfer</b> is just before cURL reads the first byte from the network (it hasn't actually read it yet). <code>time_starttransfer - time_appconnect</code> is practically the same as Time To First Byte (TTFB) from this client - 250 ms in this example case. This includes the round trip over the network, so you might get a better guess of how long the server spent on the request by calculating <code>TTFB - (time_connect - time_namelookup)</code>, so in this case, the server spent only a few milliseconds responding, the rest of the time was the network.</p></li><li><p><b>time_total</b> is just after the client has sent the FIN connection tear down.</p></li></ul>
    <div>
      <h3>Timing with Chrome</h3>
      <a href="#timing-with-chrome">
        
      </a>
    </div>
    <p>Chrome, and some other testing tools, use the <a href="https://www.w3.org/TR/resource-timing/">W3C Resource Timing standard</a> for measurements. In Chrome developer tools this looks like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7FucQd5wZiX7K01gcDGiCL/8c82a221c3ea0ad064a3a19020dca543/Screen-Shot-2018-08-04-at-12.07.37--1-.png" />
            
            </figure><p>Again, here’s how this maps onto a typical HTTP over TLS 1.2 connection, also showing the Resource Timing attribute names:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7fAas2lxyTJGoBn3X0izru/3d41a94ce5ae888bea98aba106fe1407/Screen-Shot-2018-10-16-at-14.52.48.png" />
            
            </figure><ul><li><p><b>Stalled</b> (fetchStart to domainLookupStart) is the browser waiting to start the connection, e.g. allocating cache on disk, if there are higher priority requests, or if there are already 6 connections open to this host.</p></li><li><p><b>Initial connection</b> shown by Chrome is connectStart to connectEnd. Unlike cURL timings, this includes SSL connection setup, so if you want a fair estimate of RTT, this would be <code>Initial connection - SSL</code>. If an existing connection is being reused, then DNS Lookup, Initial connection and SSL won't be shown.</p></li><li><p><b>Request sent</b> is <code>connectEnd - requestStart</code>, which should be negligible.</p></li><li><p>Similarly to cURL, if we subtract the TCP handshake time from TTFB, we can guess the amount of time the server really spent processing (again, we don't have an exact RTT timing, so this is a approximation).</p></li></ul>
    <div>
      <h3>What are we looking for again?</h3>
      <a href="#what-are-we-looking-for-again">
        
      </a>
    </div>
    <p>These measurements, including TTFB, can be helpful in diagnosing problems, and might help you to delve into a specific problem, but do they actually tell you about how well a website is performing? Ultimately, if you are looking to measure the experience of users, the time it takes for the first byte of some HTML to return isn’t effective. A web page might contain hundreds of images, it might have JavaScript and styles that need to load before you can interact. To reflect real user experience, you need to time how long until the web page becomes useful, and to take those measurements from representative sample of where your users are accessing the site from. And that's a topic for another day :)</p> ]]></content:encoded>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[Chrome]]></category>
            <guid isPermaLink="false">52qfyjBwLUIY5Bs9YR6xif</guid>
            <dc:creator>Piers Cornwell</dc:creator>
        </item>
    </channel>
</rss>