When your HTTP val becomes popular or needs to serve visitors around the world quickly, you may want to use a Content Delivery Network (CDN) to cache and serve your content.
CDNs are a network of servers that cache your content in multiple locations around the world, allowing users to access it from the nearest server, reducing latency and improving load times. Popular CDNs include Cloudflare, Fastly, AWS CloudFront, and Vercel.
For example, the Val Town Blog is hosted on Val Town, but served through Cloudflare’s CDN.
Cloudflare CDN
- Set up your Val Town Custom Domain via Cloudflare’s DNS management
- Ensure that proxying (the orange cloud) is enabled.
- Ensure the CDN configuration for that domain enables caching
- Add a Cache Rule to enable caching for all content on that endpoint, respecting the cache control headers set by your val. This is important because the default setting is to not cache anything.
- Add
Cache-Control
headers in your val (learn more) - Debug your CDN configuration by checking the response headers your browser’s devtools or via curl. If you see
cf-cache-status: HIT
, then your CDN is working correctly. If you seecf-cache-status: DYNAMIC
, then the CDN doesn’t think the content is cacheable and you may need to adjust your Cloudflare Cache Rule.
If you have any issues, we’re happy to help via email: help@val.town.
Fastly CDN
We confirmed that Fastly works with Val Town custom domains, but we don’t have a step-by-step guide yet. If you want to help us write one, please reach out!
Cache Control Headers
Cache control headers are HTTP headers that specify how and for how long a resource should be cached by browsers and CDNs.
Basic cache control headers
export default (req: Request) => { return new Response("Hello, world!", { headers: { "Cache-Control": "public, max-age=3600", // Cache for 1 hour }, });};
Hono
import { cache } from "hono/cache";import { Hono } from "hono";const app = new Hono();
app.get( "*", cache({ cacheName: "my-app", cacheControl: "public, max-age=300", // cache for 5 minutes wait: true, }));
app.get("/", (c) => { return c.html("Hello, world!");});
Disabling caching during development
It can be very fustrating if you forget that caching is enabled while you’re actively developing your val. You may not see your changes immediately, or you may see stale content.
The simplest way is to disable caching in your browser. For example, in Chrome, you can open DevTools (F12), go to the Network tab, and check “Disable cache” while DevTools is open.
We also recomend disabling all caching for *.val.run
domains, so that you can test your changes without ever worrying about caching. This way caching will only be enabled for custom domains.
For example:
export default (req: Request) => { const url = new URL(req.url); return new Response("Hello, world!", { headers: { "Cache-Control": url.hostname.endsWith(".val.run") ? "" : "public, max-age=3600", }, });};
Or in Hono:
app.get("*", async (c, next) => { const url = new URL(c.req.url); if (url.hostname.endsWith(".val.run")) { return next(); } return cache({ cacheName: "my-app", cacheControl: "public, max-age=300", wait: true, })(c, next);});