Why does Plug.Static not define an cache expiration date by default?

The SO answer you link to is not advising against ‘public’ for static assets, but setting it as default for all responses. Even responses with private data could end up in a cache of you and all parties in between with such default.

The article is about using a value for max-age, which means you know better than heuristics. Sometimes a developer does, most of the times they don’t.

Now for Plug…

For static assets, the etag is used. This is a check-value based on the content or metadata of a response. When the browser needs something it already cached once it will communicate with the webserver if that check-value is still current. If it is, the file is not returned over the wire and the browser uses the cache. So this method always requires a call, but server software is extremely fast at answering those (they already know the checksum of the file as they cache the checksum!).

As soon as the check-value changes the cache is cleared for that item.

So the default of Plug says: you (and everyone in between) can cache this asset as long as you like as we trust your heuristics. However, if the content changed you’ll need a fresh copy.