Re: Introduce contributor badges

From: Christoph Berg <myon(at)debian(dot)org>
To: Dave Page <dpage(at)pgadmin(dot)org>
Cc: Magnus Hagander <magnus(at)hagander(dot)net>, "Jonathan S(dot) Katz" <jkatz(at)postgresql(dot)org>, Daniel Gustafsson <daniel(at)yesql(dot)se>, pgsql-www(at)lists(dot)postgresql(dot)org, Andrey Borodin <x4mmm(at)yandex-team(dot)ru>, Melanie Plageman <melanieplageman(at)gmail(dot)com>, PostgreSQL Contributors <contributors(at)lists(dot)postgresql(dot)org>
Subject: Re: Introduce contributor badges
Date: 2026-10-16 14:18:41
Message-ID: atIyQWx_PwMv-PsI@msg.df7cb.de
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-www

Re: To Dave Page
> > ## Varnish cache invalidation
>
> > 4. **The image URL never changes when the image does.**
> > `/community/badge/<slug>/image/` has no file extension and no version in
> > it. The docs say Varnish applies a longer policy to images "because they
> > are considered never to change". Varnish itself is purged, but if the
> > Varnish configuration (VCL) also sends long browser cache headers for
> > images, browsers will keep showing the old image.
>
> I think purging Varnish is enough here. Badge image changes aren't
> critical, if a user sees the image somewhat longer, that doesn't cause
> trouble.

I did more research on this point, and that's the result (poking
around and by Deepseek):

Key finding: the cache policy is s-maxage, i.e. shared-cache only

docs/frontend.rst:39-46:

│ There is a longer default policy set for images, because they are considered never to change. Any view …
│ can override this default, by specifying the Cache-control: s-maxage=xxx http header … using the @cache()
│ decorator.

And that's exactly what the decorator emits (pgweb/util/decorators.py):

resp['Cache-Control'] = 's-maxage=%s' % (...)

s-maxage is honoured only by shared caches (Varnish); browsers ignore it and fall back to no explicit
freshness. badge_image itself sets no Cache-Control at all (only ETag), so:

- the "longer policy for images" is a Varnish TTL (how long Varnish holds it) — and that's the copy our
purge_urls already invalidates on save;
- browsers are never asked to cache the image long, so a changed image can't go stale in a browser under the
documented design (they'll revalidate via ETag, or not cache).

So the risk in comment #4 only materialises if the out-of-repo VCL re-adds a browser max-age for images —
which would contradict the app's own header. That's a hypothetical, not something the repo does.

Recommendation

No URL versioning. It requires a schema change, and the repository's own contract (s-maxage) is
that only Varnish caches. Adding ?v=<hash> "to avoid the question" pays a real cost to guard against a
configuration the app already argues against.

On the related "minor" comment:

> - `badge_image` fetches the image and computes its MD5 before it checks
> `If-None-Match`; storing the hash would avoid both.

badge_image is only reached on a Varnish miss, and on a miss we're
almost always about to serve the image anyway. Storing the hash only
helps the narrow (?) "Django itself receives a conditional request"
case.

So, I would say everything already works like it should.

(If we wanted, We could add explicit Cache-Control headers on
badge_image.)

Christoph

In response to

Responses

Browse pgsql-www by date

  From Date Subject
Next Message Dave Page 2026-10-16 15:18:53 Re: Introduce contributor badges
Previous Message Daniel Gustafsson 2026-10-16 12:53:51 Re: Introduce contributor badges