You're seeing bad behaviour of Safari, which boldly shows cached content while it should revalidate at the server. Next, if initially the HTML already included the counter (rather than the counter being updated using a web socket), like:
StackExchange.init({...,"inboxUnviewedCount":1}});
...
<span class="unread-count" style="">1</span>
...then somehow clicking through to any page within 60 seconds after it was initially loaded, will again show the counter value from the cached HTML.
Now, to make things complicated: Safari's Web Inspector claims the content is not fetched from cache. But using Wireshark reveals that within the first 60 seconds it does not make new requests, and in Safari's Web Inspector one then sees that the dates in the response do not change when clicking the logo, despite the label "Cached: no":

That's not the expected behaviour. When logged in, the server responds with either:
Cache-Control: public, max-age=60
Expires: Sun, 30 Mar 2014 18:55:51 GMT
Last-Modified: Sun, 30 Mar 2014 18:54:51 GMT
Vary: *
Date: Sun, 30 Mar 2014 18:54:51 GMT
...or:
Cache-Control public, no-cache="Set-Cookie", max-age=60
Set-Cookie: ... expires=Tue, 30-Sep-2014 18:54:51 GMT; path=/; HttpOnly
Expires: Sun, 30 Mar 2014 18:55:51 GMT
Last-Modified: Sun, 30 Mar 2014 18:54:51 GMT
Vary: *
Date: Sun, 30 Mar 2014 18:54:51 GMT
Note the Vary: *
header above, for which the specifications say:
When the cache receives a subsequent request whose Request-URI specifies one or more cache entries including a Vary header field, the cache MUST NOT use such a cache entry to construct a response to the new request unless all of the selecting request-headers present in the new request match the corresponding stored request-headers in the original request.
[...]
A Vary header field-value of "*" always fails to match and subsequent requests on that resource can only be properly interpreted by the origin server.
In Safari, within the 60 seconds that the cache is valid, clicking the logo will make Web Inspector show it makes a new request for the page without any restrictions. (Again: Wireshark reveals that no such request is made at all, so that information is false.) Only when waiting a full minute after the last request, clicking the logo will make Safari truly send a new request, with an additional conditional request header:
If-Modified-Since: Sun, 30 Mar 2014 18:54:51 GMT
Chrome and Firefox always make a real request. Chrome then always includes If-Modified-Since
, while Firefox never sends that. Even with that header, when logged-in, the Stack Exchange server always seems to return a new page and never returns 304 Not Modified
, not even on low-traffic sites such as Meta.
When not logged-in, 304
is used. And one sees that some server-side cache is doing some countdown, where the number 60 counts down to zero:
Cache-Control: public, max-age=34
This first made me think that Safari somehow got some cached server response while logged-in as well, until Wireshark showed me Safari's Web Inspector was showing fake details.
Cache-Control: public, max-age=60
for its HTML pages. So your browser caches the page for 60 seconds, and does not reflect the read status of the notifications. – Antony Mar 30 '14 at 5:44Vary:*
in the headers, @Antony: shouldn't browsers always ask the server if the cache is valid? (My Chrome does so usingIf-Modified-Since
in the request.) Also, I wonder (but could not check right now) if notifications are ever in the HTML source. (When I load the page, I immediately see the socket opening; I always figured it would get any notifications at that point, not in the HTML, but you might be right there.) – Arjan Mar 30 '14 at 9:11$.get(location.href)
in the console and verified that the notifications are in the HTML source. – Antony Mar 30 '14 at 9:16