Hacker News new | ask | show | jobs
by kentonv 23 days ago
Realizing there's a more fundamental piece I'm not explaining well here.

Our architecture is something like:

ingress -> routing -> security -> workers -> cache -> origin

That is, workers run "in front of" cache. That's usually what you want. Workers run on the edge, so putting them in front of cache doesn't cost anything in terms of latency, and there's a lot of useful stuff you can do only if they run in front, e.g. serving pages from cache but customizing them for specific users.

Putting workers behind cache is an architectural change. All of the logic around routing to them lives in front of the cache. And it makes Workers a lot less useful.

We weren't that excited about it until we had a clearer story for how to run custom logic on both sides of the cache, but it was pretty unclear how to do that in a nice way until the recent developments around ctx.props, ctx.exports, channel tokens, etc.

2 comments

Does that new architecture make it more expensive to serve worker’s static assets and do worker-to-worker invocations? Or just harder to measure?

This change in billing makes enabling caching not such a straightforward decision, and encourages separating cached and non-cached parts of your workers into two separate workers, which is a bit annoying.

I wasn't personally involved in pricing here so I can't really say exactly why it is the way it is.

However, I'd note that, in terms of our costs, it's often cheaper for us to run your Worker than to serve from cache. Consider that Workers run locally in whatever edge location the request landed in. We are not saving any bandwidth costs by putting the cache in front of Workers rather than behind, and we've built an architecture such that running a Worker is extremely cheap, almost free.

In that light, making cache hits free would basically be giving away money. To be honest, that is another reason why implementing cache in front of Workers has been held back so long. I think the team finally decided that the only way we can deliver it without giving away too much money is to charge full price for the requests. Workers pricing is already incredibly generous, and we do need to run a business at the end of the day.

(Of course, a cache hit still saves you the CPU pricing. CPU time pricing more directly translates to costs for us, so that makes sense.)

I admit the side effect on static assets is a little weird. But no other provider offers unlimited free static asset serving to start with -- so it's only weird relative to our own unreasonable standards. :) I think the thought here is that if you need caching in front of Workers, that implies you are doing complex work in Workers and getting a lot of value out of them. So a bit of "price segmentation" kicks in here. That said, you can work around it by serving static assets from another hostname, etc.

No objection towards charging for cache hits, when the worker would have ran. That (except in worker-to-worker invocations) is always a strict upgrade, when it comes to pricing.

Worker-to-worker invocations also now participate in the cache, so despite the pricing increase, at least we’re getting some added value.

But for static assets in particular, I don’t see what value the cache is adding, so it feels like pure price segmentation.

Or, to put it another way, you were already caching the static assets and not having the workers serve them. Now you're doing the same thing, but charging for it.

blog post didn't cover two details re stale-while-revalidate:

1. What headers does content that will revalidate use on client. Eg can a react hook trigger if a cms json revalidates?

2. If edge worker can call database worker: if database worker sends stale while revalidate, does that revalidate whole worker chain?

btw overall very cool, esp fine grained cache for authed/etc data