
Cloudflare Workers: Run JavaScript Service Workers at the Edge - thomseddon
https://blog.cloudflare.com/introducing-cloudflare-workers/
======
js2
This is probably the best annoucement of a new feature I have ever read. It
makes an analogy to an existing technology. It provides a clear description of
the new feature. It provides clear examples of how to use the new feature with
a link to a sandbox so you can run and modify the examples. And it explains
the thought process behind the implementation. In additon, I didn't notice a
single typo, spelling or grammar error.

Also, this feature is pretty cool!

~~~
konradzikusek
> I didn't notice a single typo

JavaScript is spelled incorrect all over the place.

Awesome feature and post!

~~~
kempwatson
That would be "incorrectly".... be careful with criticism.

~~~
abiox
do you mean that one must be completely flawless?

~~~
lugg
Only when you're being pedantic.

~~~
abiox
i guess that leaves one's fate in the hands of passers by.

------
kentonv
Hey all! This is my project at Cloudflare.

(You may remember me as the tech lead of Sandstorm.io and Cap'n Proto.)

Happy to answer questions!

~~~
aboodman
Hey Kenton, should've guessed you were behind this. Lovely design, great work.

I'd be curious to learn more about the implementation (did you lift the
existing SW implementation from blink somehow, or reimplement it)?

~~~
aboodman
PPS - it is probably too late for this, but one of the last things I worked on
at Google was Gin:

[https://chromium.googlesource.com/chromium/src.git/+/lkgr/gi...](https://chromium.googlesource.com/chromium/src.git/+/lkgr/gin/)

A bindings layer for v8 that was specifically intended to make implementing
web-style APIs outside of Blink easier. At the time at least, refactoring
things like SW out of Blink was ~impossible.

~~~
kentonv
Doh, indeed, wish I had seen that earlier. V8's raw API is... tricky.

~~~
aboodman
Darn, I wish you'd seen it too :). Sounds like you came to similar conclusion
I did -- using C++ templates to stamp out v8::FunctionTemplate and
ObjectTemplate instances.

I was pretty happy about how Gin turned out and always thought it would be
nice to put it on Github where it would be easier for people to reuse.

But at the time Chromium still didn't allow all the modern C++ features, so
Gin had to depend on base::Callback, which made it hard to extract cleanly.

------
Erwin
Obligatory transformation of cloud to you-know-what:

[https://cloudflareworkers.com/#9bdc354e936c05a4a1d7df7eb0d7f...](https://cloudflareworkers.com/#9bdc354e936c05a4a1d7df7eb0d7f672:https://blog.cloudflare.com/introducing-
cloudflare-workers)

~~~
JohnDotAwesome
[https://cloudflareworkers.com/#1f3220d90979ded0b1f5413db0eac...](https://cloudflareworkers.com/#1f3220d90979ded0b1f5413db0eacf40:https://blog.cloudflare.com/introducing-
cloudflare-workers) this fixes the styling issues :D

------
niftich
Kudos for re-using an existing API when one was already available in the same
language for a very similar usecase.

Any time you commit to someone else's API -- whether it's an actual industry
standard, or simply some de facto widely used paradigm -- you incur risks;
conversely, now that you're a vested participant, consider being involved in
the future of the spec so it can evolve where it needs to meeting emerging
needs around its new uses.

~~~
kentonv
Absolutely! One reason we wanted to get this out in public before it's ready
is so we can properly engage with the spec writers (and the V8 team).

That said, I am amazed by how well the spec fits as-is. I don't usually like
other people's API designs but in this case I think they did a really good
job, and I've been pleased not to have to think about API design myself.

------
j_s
Paging HN user johansch from his comment on the Cloudflare Apps mitm
JavaScript injection discussion 3 months ago:

johansch: _All I want is my code running on your nodes all around the world
with an end-to-end ping that is less than 10 ms to the average client_

dsl: _Akamai Edge Compute is what they are asking for_

[https://news.ycombinator.com/item?id=14650025](https://news.ycombinator.com/item?id=14650025)

------
manigandham
This is fantastic. Fastly is great but hard to use with Varnish VCL, and no
other CDN had any real scripting capabilities. The service worker API is also
a lot better than serverless cloud functions or lambda@edge.

------
narsil
Great product announcement post! I especially liked the Q&A section's reasons
for not choosing alternatives.

Is the lack of maturity also the reason for not choosing something like vm2
for NodeJS
[https://github.com/patriksimek/vm2](https://github.com/patriksimek/vm2)

~~~
kentonv
I actually didn't know about that one.

Looking briefly, it looks like it's based on creating separate contexts, but
not separate isolates. Contexts within the same isolate can be reasonably
secure (it's how Chrome sandboxes iframes from their parent frames, after
all), but they still share a single heap and must run on the same thread.
Isolates can run on separate threads. We prefer to give each script its own
isolate, so that one script using a lot of CPU does not block other scripts.
We also want to be able to kill a script that does, say, "while(true) {}".

So yeah, it looks like a neat library but it probably wouldn't suit our needs.

------
TheAceOfHearts
This sounds like a really powerful feature. I love how it uses JavaScript,
which makes it much more approachable for web developers.

My experience with Service Worker APIs hasn't been very positive, although I
don't have any suggestions for ways it could be improved, so I apologize for
the non-constructive feedback. Maybe after using it more I'll change my mind.
I recognize that everyone involved is likely working hard to provide an API
that's capable of handling a wide range of problems, many of which I likely
haven't even considered.

Here's a more actionable complaint: fetch doesn't support timeout or abortion.
I have a hard time understanding how this isn't a problem for more people. Say
what you will about XMLHttpRequest, at least it supports these basic features.
As an end-user, I always find it absolutely infuriating when things hang
forever because a developer forgot to handle failure cases.

I'd love it if you published a locally runnable version. Aside from making it
easier to configure and experiment, it would give me peace of mind to know
that I could continue to use the same configuration if Cloudflare decided to
terminate my service.

~~~
kentonv
Abortable fetch actually just recently became a thing, as in the Github issue
was closed 9 days ago. More info:

[https://developers.google.com/web/updates/2017/09/abortable-...](https://developers.google.com/web/updates/2017/09/abortable-
fetch)

We'll be implementing soon.

------
wcdolphin
Could this be used for HTTP Push across domains? I would love an easy way to
take advantage of HTTP Push for assets hosted on S3 without routing requests
to my origin server.

~~~
kentonv
Yes, your worker can make subrequests to other domains, and serving some
assets out of S3 is a use case we specifically want to enable.

I haven't looked into how specifically to expose HTTP Push in the API but that
certainly seems like something we should support.

~~~
spankalee
Please, add support HTTP/2 push!

This is very, very awesome work. My team has been working on enabling the PRPL
pattern[1] and differential serving on a few platforms, and edge caching has
been a problem. We've tried to use Vary: User-Agent, but that leads to low
cache hits. This API would let us to much smarter UA sniffing at the edge.

From there we just need to parse some responses like JS and HTML, to be able
to push their sub-resources, for an instant speedup and great caching for
fine-grained deployments.

[1]:
[https://developers.google.com/web/fundamentals/performance/p...](https://developers.google.com/web/fundamentals/performance/prpl-
pattern/)

~~~
mdale
Http/2 push is interesting here. Beyon static assists I wonder about read API
orchestration or equivalent of graghQL on edge. I.e a single request comes in
and it's broken apart against catchable resources and pushed back to the
client from cache where possible.

~~~
kentonv
That's actually one of the canonical use cases we thought about while
designing. It seems splitting graphql queries into cacheable chunks is a
common need.

------
Gys
So in a way this is similar to for example AWS Lambda ? It can process
incoming http requests in many ways ? Fascinating idea.

Is there any indication on price level ? And what about runtime duration ?

~~~
kentonv
It's actually somewhat different. AWS Lambda is intended to act as your origin
server. Generally your Lambda functions run in a small number of locations,
not necessarily close to users.

Cloudflare Workers will run in all of Cloudflare's 117 (and growing)
locations. The idea is that you'd put code in a worker if you need the code to
run _close to the user_. You might want that to improve page load speed, or to
reduce bandwidth costs (don't have to pay for the long haul), or because you
want to augment Cloudflare's feature set, or a number of other reasons. But,
generally, you would not host your whole service on this. (Well, you _could_ ,
but it's not the intent.)

We haven't nailed down pricing yet, but we've worked hard to create the most
efficient possible design so that we can make pricing attractive.

~~~
michaelt

      We haven't nailed down pricing yet
    

One of the things I like about AWS is the price doesn't jump from $0/year
directly to $240/year the way cloudflare does.

~~~
bogomipz
Indeed, this would be the second product announcement from Cloudflare in 3
days that didn't have any pricing available.

------
throwaway84736
Have you guys considered side channels?

Seems like whenever there's co-execution (VMs, JavaScript, etc) there seem to
be side channel leakages.

~~~
kentonv
We're certainly aware of them, but haven't spent a lot of time focused on this
issue yet. Of course, the issue exists on all forms of shared compute. So if
you're going to do crypto, you'd better make it constant-time. Which is... not
easy in Javascript. (But we will provide the WebCrypto API, which might help.)

There is a theoretical solution that we might be able to explore at some
point: If compute is _deterministic_ \-- that is, always guaranteed to produce
the same result given the same input -- then it can't possibly pick up side
channels. It's possible to imagine a Javascript engine that is deterministic.
The fact that Javascript is single-threaded helps here. In concrete terms,
this would mean hooking Date.now() so that it stays constant during continuous
execution, only progressing between events.

That said, this is just a theory and there would be lots of details to work
out.

~~~
SomeStupidPoint
> There is a theoretical solution that we might be able to explore at some
> point: If compute is deterministic -- that is, always guaranteed to produce
> the same result given the same input -- then it can't possibly pick up side
> channels.

Doesn't this require the timing and interleaving with other processes also be
deterministic? ...which seems hard to guarantee with modern CPUs, async IO,
and shared execution.

~~~
kentonv
If you don't provide (real) time as an input to the program, then non-
determinism of time does not affect determinism of the program. At least, in
theory. It's definitely a long way from there to practice.

~~~
SomeStupidPoint
That's true -- but "the program" is also any code using yours as a middle-
step, which is the case of a network service is a huge number of people. So
anything that requires total program control rather than subroutine enforced
safety is a nonstarter.

The timing may occur outside of your control, and then statistical profiling
used. If the timing of a reponse to a network request has a time component
that depends on shared load, then you have a side-channel.

------
polskibus
I read the article, but I'm not sure what this technology is enabling really.
Can it be thought of as a new player in the lambda/serverless category? Does
it have any advantages to using other serverless stacks like aws lambda or
azure?

~~~
kentonv
The advantage is that the code runs close to your users. 90% of the people on
Earth are within 10ms of a Cloudflare location, so by pushing your code out to
the edge you can make your site faster. You also save on the cost of
transmitting data around the world.

------
poorman
Seems like this plus the Cloudflare Apps could yield some interesting
projects.

~~~
eastdakota
Yup. :-)

~~~
shallot_router
This seems like it has a ton of potential. I'm already thinking of the
possibilities for my own Cloudflare-proxied sites.

I hope it's not priced too harshly. Hopefully an added monthly flat rate
rather than per-request pricing?

------
skrebbel
Sounds like this could be a pretty trivial way to load balance React
prerendering. As long as the react code fetches all data in 1 call it should
be at least as efficient as doing it all in Nodejs on your server.

~~~
JohnDotAwesome
Relevant example using Preact
[https://cloudflareworkers.com/#87ec550da87ab3f7de756a4979c00...](https://cloudflareworkers.com/#87ec550da87ab3f7de756a4979c0085b:https://tutorial.cloudflareworkers.com)

------
peterwwillis

      - Is it "Cloudflare Workers" or "Cloudflare Service Workers"?
          A "Cloudflare Worker" is JavaScript you write that runs on Cloudflare's edge.
          A "Cloudflare Service Worker" is specifically a worker which handles
          HTTP traffic and is written against the Service Worker API.
    

Consufing naming convention. Now you have to say 'worker worker' or 'non-
service worker' so nobody has to wonder if you meant 'service worker' when you
only said 'worker'.

~~~
kentonv
Not really, because once there are workers other than Service Workers, they'll
have their own names. To be clear, a Service Worker is one kind of Worker. At
the moment it's the only kind, but we could introduce others in the future.
For instance, maybe we'd introduce a "DNS Worker" that responds to DNS
requests.

Also note we didn't invent these terms. "Workers" and "Service Workers" are
W3C standards.

~~~
peterwwillis
Ok. If you're going to have a DNS worker, wouldn't it make more sense to call
the http one the HTTP worker? Isn't DNS a service?

~~~
kentonv
We called it a Service Worker because the API follows the W3C standard Service
Worker spec:

[https://www.w3.org/TR/service-workers-1/](https://www.w3.org/TR/service-
workers-1/)

[https://developer.mozilla.org/en-
US/docs/Web/API/Service_Wor...](https://developer.mozilla.org/en-
US/docs/Web/API/Service_Worker_API)

I agree that the naming is not completely intuitive, but these are the names
that exist and so we're using them.

I'm not aware of any similar spec for DNS workers so I figure we'll use
whatever name we want there.

------
forcer
Could this be used to make Cloudflare respond to HTTP POST requests?

~~~
kentonv
Yep.

    
    
        if (request.method == "post") { ... }

------
drdaeman
Oh my. Is there any form of persistence, present or planned?

If there is - this means that there (eventually) will be a way to have logs
from the edge servers. I'm just thinking about a worker that would collect the
requests and responses data in some circular buffer, and try to push it to the
origin server. Eventually, the data will get through, so no CDN-returned 52x
("web server is not responding" etc) errors would go unnoticed.

~~~
kentonv
We won't offer writable storage at the edge in v1, but you could always make a
background request to push these events back to some log service you maintain
(on separate infrastructure from your main service to make simultaneous
outages unlikely). Note that you can make background requests that happen
after the main response has already returned (but still subject to the per-
request CPU limits, etc.).

We're thinking about how to do writable storage, but it's tricky, since one
thing we don't want is for developers to have to think about the fact that
their code is running in hundreds of locations.

------
renke1
So, can I use this to do this:

Render your SPA (different index.html) when a login cookie is set and
otherwise render your landing page (yet another index.html)? - Such that that
my [http://example.com](http://example.com) can always be cached (unless it
needs to hit the server where the same logic is implemented).

And in general, how do you manage your landing page vs. your SPA?

~~~
scottmf
Maybe I’m not quite understanding what you’re asking, but I think you can do
this with client side service workers already.

------
mxuribe
This is really interesting; kudos to Cloudflare for launching what seems like
a cool thing!

Also, agree with other commentators here; nicely-written blog post!

------
tyingq
Very nice. Are there plans to expand on it? For example, some way to allow
state to be kept at the edge as well.

~~~
jgrahamc
Yes. We plan to. We are releasing this to find out precisely what people need.

~~~
pbowyer
Some way to implement cache tagging and fast invalidation based on tags (a la
Fastly) would be good. Without storage I can't see a way to keep a hash of
currently valid tags - but I will play!

------
valentinvieriu
Great addition to your services. I really want to see the pricing. Also I'm
quite excited to see how this will play along with the apps concept. Do you
plan also to introduce a monetisation system for the apps? It will be a good
incentive then for developers to get some nice income.

~~~
kentonv
As a matter of fact, the monetization part already exists: Cloudflare Apps is
a thing today, including paid apps. Today, though, they are limited to
injecting client-side code. Once Cloudflare Workers are integrated with Apps,
they'll be able to include server-side code too.
[https://www.cloudflare.com/apps/](https://www.cloudflare.com/apps/)

PS. There's an investment fund targeting Cloudflare App developers:
[https://www.cloudflare.com/fund/](https://www.cloudflare.com/fund/)

------
ohnoesjmr
Sounds very cool, but first thing that hit my head: Sounds like a perfect tool
to DDoS someone?

~~~
kentonv
We've thought of that, and it won't be. :)

------
fowl2
This is really cool! I wonder if this will become the new "S3 API" and get
everyone to copy^H^H^H^H implement it.

Also a little concerned about writing anything substantial without an onprem
version!

~~~
kentonv
Yes, it's my hope that Service Workers will be recognized broadly as the
standard API for this.

FWIW I've seen several different folks saying they're working on implementing
a Service Workers API shim on top of Node, which would be a great way to get
an on-prem version, and should not be very hard to do.

------
hdhzy
This is excellent news! Now I wish AWS Lambda and alternatives also supported
Service Worker API (Google Cloud Functions has express like API).

------
michaelmior
How will billing work for this? It seems like I could conceivably write an
entire application that just runs as a Service Worker.

------
djhworld
Is this similar to Amazon's Lambda@Edge?

~~~
maybeiambatman
Sounds like it. I think Cloudflare's edge (no pun intended) is going to be
their 110+ locations to host this. As opposed to Amazon's 93 I believe? (If
all cloudfront spots support lambda@edge that is)
[https://aws.amazon.com/cloudfront/details/](https://aws.amazon.com/cloudfront/details/)

~~~
eloff
I would say at 117 edge locations vs 93 Cloudflare will have lower latency,
but most notable in markets that most companies care least about. Probably of
more importance is by using embedded V8 as opposed to a process-level sandbox
running Node.JS, the Cloudflare service worker will have a much faster startup
time in all locations. I seem to recall from tests in Lambda that we're
looking at 40-50ms, which is actually substantial given how close these
locations often are to the user. But the biggest edge in my books is
CloudFront bandwidth is ridiculously expensive and Cloudflare doesn't charge
(directly) for bandwidth. Bandwidth often being the single biggest line item
in your AWS bill if you get a lot of traffic.

------
boundlessdreamz
offtopic: can cloudflare be used as a CDN for just assets? The cloudflare docs
talk only about using it as CDN for an entire site.

~~~
shallot_router
Technically, yes, but as I understand it, they frown upon it and could
potentially terminate your account. See this section of their ToS
([https://www.cloudflare.com/terms/](https://www.cloudflare.com/terms/)):

>SECTION 10: LIMITATION ON NON-HTML CACHING

>You acknowledge that Cloudflare’s Service is offered as a platform to cache
and serve web pages and websites and is not offered for other purposes, such
as remote storage. Accordingly, you understand and agree to use the Service
solely for the purpose of hosting and serving web pages as viewed through a
web browser or other application and the Hypertext Markup Language (HTML)
protocol or other equivalent technology. Cloudflare’s Service is also a shared
web caching service, which means a number of customers’ websites are cached
from the same server. To ensure that Cloudflare’s Service is reliable and
available for the greatest number of users, a customer’s usage cannot
adversely affect the performance of other customers’ sites. Additionally, the
purpose of Cloudflare’s Service is to proxy web content, not store data. Using
an account primarily as an online storage space, including the storage or
caching of a disproportionate percentage of pictures, movies, audio files, or
other non-HTML content, is prohibited. You further agree that if, at
Cloudflare’s sole discretion, you are deemed to have violated this section, or
if Cloudflare, in its sole discretion, deems it necessary due to excessive
burden or potential adverse impact on Cloudflare’s systems, potential adverse
impact on other users, server processing power, server memory, abuse controls,
or other reasons, Cloudflare may suspend or terminate your account without
notice to or liability to you.

I think in practice, unless you have a very popular website or are abusing it
in some way, they probably wouldn't care or even notice. But you'd still be
taking a gamble.

(I don't work at Cloudflare though so take whatever I say with a grain of
salt.)

~~~
pilom
Wow, thanks for that info! Our enterprise account uses CF as a CDN for medium
sized (~50MB) video files and I just assumed that they were ok with everyone
doing that. I guess not.

I guess the answer for the OP then is, get an enterprise account and you can
do whatever you want.

------
angersock
This is really cool...but _why_?

~~~
tyingq
I thought of a few use cases...

A more granular way to block requests than what cloudflare provides (IP, BGP
AS, country)

Tokenizing credit cards at the edge if you have a payment provider that
supports that, and are using CF's PCI compliant environment.

Injecting a unique ID into requests for log correlation. You get collisions if
you do this via browser javascript for various reasons. I'm assuming v8 has a
better Math.random(), or that you would at least be able to find a workaround
since it's in one stack.

I'm sure there's more.

~~~
angersock
Also some good use cases. :)

------
briandear
Can’t you already do this with Fastly and Varnish?

