CLJS & AWS Lambda

clojurescript

#1

I want to learn about running ClojureScript on AWS Lambda, but the ecosystem is hard to understand. How do people deploy to Lambda? How do you test your code locally? I’d be grateful for experience reports, recommendations and other links that can point me in the right direction.


#2

I have been using serverless-cljs-plugin for lamdbas for very long time. Serverless Framework is easy to get started with and makes it easy to accomplish big tasks like setting up an API Gateway.

Now, my personal choice was to use the lumo compiler (which I contributed) plus inf-clojure but you can easily use cljs + lein - it actually has been developed with that in mind.

Serverless is also so pluggable that it is very easy to write custom tasks for many different purposes, when you cannot find a plug-in that does it already.

So when does it break? In my experience the multi cloud promise has not really been delivered. Also, if you plan to use other AWS resources you might need to write a lot of Cloud formation. You can use Serverless for it, but I don’t like Cloud formation. Serverless does not play very nicely with CI also, because it stores locally the AWS state of the deployed resources.

Therefore, recently I moved to compiling the zip and using Terraform for deployment. Terraform IMHO is the right tool for the job when you deal with properly sized stacks.

Too many words, let me know if you have any specific question :slight_smile:


#3

Not related to Cljs, but Martin Fowler wrote a very detailed overview about the whole serverless thing https://martinfowler.com/articles/serverless.html
It includes many references to AWS Lambda functions, you might find it useful.


#4

Good stuff, keep em coming! Quick summary of what I’ve learned so far.

Re: the article on martinfowler.com, very useful, I always appreciate longform explanations.

Re: deployment tools, I found that even just getting a simple “echo” Lambda/Gateway endpoint off the ground requires creating a whole litany of resources (function, gateway, resource, method, permissions, policies). Setting things up manually through imperative CLI commands is possible but tedious, especially when updating an existing stack.

So almost everyone uses a declarative description of the resources. CloudFormation does that but it’s so verbose that it gets unwieldy fast. The main options seem to be:

  • AWS SAM is an extension of CloudFormation’s yaml syntax. It includes templates that expand out to CF resource descriptions.
  • serverless is a project that targets multiple cloud providers and provides a simplified CLI for creating APIs using lambda functions
  • terraform is a general-purpose, declarative cloud provisioning tool which also includes a module for Lambda/API Gateway

#5

Quick update. SAM has a lot of rough edges. You can make it work but you need to dive into CloudFormation and be prepared to search for snippets on Github/StackOverflow.


#6

Do you have a requirement to run ClojureScript instead of Clojure? If you can run Clojure instead, Ions appears to be a relatively easy way to use lambdas:

Even if Ions aren’t a good fit, it may be worth exploring using Clojure instead of ClojureScript. There is a good analysis of the tradeoffs, including performance and startup time, here:


#7

(Of course, if you have a hard requirement to use CLJS - say, to interop with some existing CLJS or JS code - then this won’t apply :slight_smile:)


#8

@bbrinck, good point. Clojure on Lambda is an option that we’re exploring as well. The JVM is still the better platform for writing servers compared to Node.

FWIW, from my experiments the CLJS part of the proces is pretty straightforward. All you need to do is to compile to a bundle that does the equivalent of this line, e.g.:

(goog.object/set js/module.exports "handler" (fn my-handler [event context callback] ...))

The trickier bit by far has been dealing with general lambda bureaucracy, i.e. setting up all the necessary resources and permissions on AWS.


#9

Ah, I see. In that case, definitely take a look at Ions. My understanding is that they solve exactly this problem - they provide sensible lambda configuration out of the box and also allow rapid deployment of code changes via AWS codedeploy.