Microservices with Crystal and Kemal

I came across the Crystal programming language today and really caught my eye. It’s advertised as

“Fast as C, slick as Ruby”.

One of the things that I noticed is that you’re able to do a lot of stuff with a small amount of code. The following example creates a simple HTTP server.

Isn’t that a beauty? I really like the syntax compared to something like Go.

Kemal is a web framework written in Crystal and it supports the following features.

  • Support all REST verbs
  • Websocket support
  • Request/Response context, easy parameter handling
  • Built-in and easily extensible middleware
  • Built-in JSON support
  • Built-in static file serving
  • Built-in view templating via ECR

Kemal can be added as a dependency using the Shards dependency manager.

I’ve decided to create a simple Payment Service using Kemal and embed it into a lightweight Docker container. Just to play around.

You can initialize a Crystal app pretty quickly using the cli.

$ crystal init app payment-service

That will generate a project structure for you and it includes some example code.

The Payment Service receives a payment request and executes a fake payment. Once the payment is executed it returns the results to the client. It only accepts amounts lower than €2500.

The PaymentExecutionService looks as follows.

The Crystal cli can be used to compile and run the microservice.

$ crystal build src/PaymentService.cr -o bin/PaymentService
$ ./bin/PaymentService
[development] Kemal is ready to lead at http://0.0.0.0:3000

You can now browse to http://localhost:3000/pay?amount=1000 and you should get the following reply.

Paid EUR 1000.0

We can containerize this microservice and potentially deploy it to Kubernetes or some other orchestrator. I’ve used the following Dockerfile to containerize the microservice.

Let’s build it and run it.

$ docker build -t payment-service:1.0 .
...
$ docker run -d -p 3000:3000 payment-service:1.0
0fe94f7461f880739c18ee4f50c4ba66b4272cf6da565062b4ee0a2ab1b2ccc6
$ curl http://localhost:3000/pay?amount=3000
EUR 3000.0 is way too much!

Let’s take a look at the size of the image.

$ docker images payment-service
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
payment-service     1.0                 86790907d364        About an hour ago   5.31MB

As you can see the image is only 5.31 megabytes. That’s a pretty small footprint.

That’s it folks!