Could you please describe your stack for web apps development in OCaml with reasoning about it?

Could you please describe your stack for web apps development in OCaml with reasoning about it?


I’m curious about this as well. This is what I’ve understood so far:

  • there are no production-grade database bindings for Postgres. Discussion here.

  • there are no full-fledged web frameworks in the OCaml ecosystem with commercial users and maintenance. Ocsigen has quite a bit of learning curve and probably is not a good fit for small inexperienced teams.

  • there is Opium by @rgrinberg, which adds routing and HTTP niceities to CoHTTP, which is a robust web server. It is minimalist compared to things like Rails. But with a session management library like inhabitedtype/ocaml-session and OCaml’s power and type-safety, we can hand-roll a sturdy web app.

Only if there was a better story in the database binding section… :slight_smile:

1 Like

About postgres in production:

Markus’ Posgres bindings are very very solid
(PG’OCaml, without the syntax extension, is fine too, and more Lwt-friendly, but if you need TLS, you need to setup tunnels separately).

About web-development stacks:

We’ve used the whole Ocsigen/Eliom stack in a decently big project,
it was a few years ago, it was overall good, but indeed the whole stack at once can be a bit
hard to learn and a bit of a moving target (much less nowadays).
And it could be a bit annoying to manage flexible deployments (I mean compared to what we are used to in OCaml, but not compared to popular frameworks in mono-typed languages…
anyway nowadays it just means “use docker”).

In a few much more recent projects, I’ve used an Ocsigen-light setup:
Cohttp + Js_of_ocaml + Tyxml_js + (Búnzli’s) react.
That’s really nice and very "flexible/hackable” (things like having the result of js_of_ocaml's compilation lifted on the server code as a string, or using JSONP servers, webworkers, etc.).
There is a one-time build-system & communication initial setup cost though because everything is custom (jbuilder/dune has made things easier there too).


I’d second that. After playing with it when building ezpostgresql, the impression I get was that these bindings are pretty much stable, in the sense that most postgresql features have proper representations in it so you don’t have to write any C code. One thing to note is, to achieve that, the API is not necessarily user- or FP-friendly. However, one can build a functional abstraction on top of it if they want to (which ezpostgresql is intended to be for me personally, and has been so far).

For webservers, I’m a fan of a lightweight ones (e.g. Express, Sinatra, Flask, etc.), so Opium hits the spot nicely. It supports middlewares so you can pretty much do anything with it. I seldom have to think about HTML and templating since the frontend will usually get separated anyway (and if it does, you might be interested in Reason and ReasonReact).


There is a one-time build-system & communication initial setup cost though because everything is custom (jbuilder/dune has made things easier there too).

Do you have an example online of such a setup ?

1 Like

Not everything is open-source, but: → the first one I did like this was by following CueKeeper’s example, so the code of the webui has grown to be quite messy and the build system is still based on solvuu-build/ocamlbuild.
A couple of years ago, we followed the trend and switched from adtgen to ppx_deriving_yojson for the serialization/communication, I regret that. → used to have a WebUI (I ditched it because of pseudo-real-time constraints that led me to another idea, not because it didn’t work).
this merge-request shows the first setup of the webui:
(then following git history we can see the webapp getting more complex) → this has no server-side; the webapp communicates with an OCaml toplevel running in a webworker (this time it’s made with jbuilder!)

And in the not-yet-open-source/work-in-progress/shameless-plug category, I’ve been geeking-out on the website of my band
(mostly client-side but there is an optional CoHTTP-based JSONP server to collect statistics, it uses jbuilder, and the “Tyxml_js.R” whole stack, and the build also generates a static “no-script” version of the website)



We worked a lot to reduce Ocsigen’s learning curve in the past few years. Also interfaces are much more stable now. If you plan to build a client-server Web and mobile app, you will definitely save a lot of time with Eliom, even if your team needs to learn the framework.

If you plan a server-side only Web site, Eliom provides some very useful features like a complete and powerful session mechanism (very easy to use) and html static type checking (with Tyxml).

A few words about the stack we use at Be Sport:

  • The mobile (iOS and Android) and Web apps are written with one single multi-tier Eliom code (we use Ocsigen-Start as a basis).
  • We use mainly postgresql with PGOcaml (even if we are not 100% happy with this solution). We use a pool a read-only db servers (currently with pgpool).
  • Everything is hosted on AWS, with docker containers, and Elastic load balancer to dispatch to several instances of Ocsigen server (with SNS and SQS to dispatch notifications to all servers, and Firebase to send notification to mobiles apps).

Vincent Balat


I really like Eliom and built a simple web-app with it for teaching purposes. Is there any work to make sure its performance matches httpaf?

Also, it’d be a really good idea to integrate with bucklescript for improved performance/clarity of javascript code. I know the Reason people are amazed when I describe how powerful Eliom is.

Can you elaborate a bit on the issues you’ve run into? In my experience using both atdgen and ppx_deriving_yojson on different projects they both have their downsides. If you have time it would be interesting to hear the areas where one has been more useful to you than the other.

There is no plan to integrate Eliom with Bucklescript. I am not sure it has better performances than Js_of_ocaml and you can achieve good clarity of Javascript code with Js_of_ocaml with options -g --pretty(and possibly --no-inline) (even if you probably don’t want that in production, for efficiency reasons). Also you need 100% compatibility with OCaml to run Eliom programs.

Eliom is now usable with Reason syntax (we will announce this soon, with a translation of the documentation), with js_of_ocaml. We need beta-testers for this.

There is now a branch of Ocsigen server which is using cohttp, and Eliom has been adapted. This will be released once it is tested enough, if performances and stability are ok. I don’t know if measurements have been done to compare current implementation with httpaf.


ppx_deriving_yojson is very well integrated with findlib and worked totally fine indeed esp. with poorly configurable build-systems.

But once you have a build system that’s hackable enough (omake, dune) maintaining the protocol(s) in separate .atd files is much cleaner and flexible (e.g. it’s much easier to write/manage versioned protocols).

Everytime, the ppx_* have been the last bit that could not switch to the next version of OCaml (or prevented us from trying some improvement or bug-fix on trunk or some GPR).

Writing a new ATD output is actually way easier than creating a ppx_deriving plugin and requires very little maintenance (

Most ppx_derivings don’t work with GADTs or objects, so anyway, if you want to get “serialization for free” by just adding [@@deriving ...] to your types, you’re forcing yourself to use a subset of OCaml that’s mostly isomorphic to ATD :slight_smile:


Thank you for the detailed response!

It’s true that the OCaml PostgreSQL API is not the most user-friendly. When I took over maintenance, it had already been written using the OCaml object system. I kept it for backward compatibility, but maybe it would have been better in retrospect to change the API to a more functional style. If anybody ever wants to improve that situation, please don’t hesitate. It should be easy to reuse the C-stubs for a functional API. If you can map the functional API to the object API, you could maintain backward compatibility without much code duplication, making transitioning a smoother process.


How do you use a bunch of atd files in dune without writing one rule for each file?

1 Like

My approach: write the bulk of the client and server functionality in OCaml, compiled by jsoo (bucklescript is an option, but I want to reuse OCaml libraries mainly, so jsoo seems a better fit). For server, use node.js/express/password.js to wrap the OCaml, and to handle login etc (although ultimately there is an OCaml function which checks username/password). Communication ocaml <-> node server <-> ocaml client is through json. Essentially I do this because I don’t want to think very much about sessions, cookies etc, nor do I want to spend time learning cohttp or opium (both are good, but it looked like it was going to take time to get session management working). This is very lightweight and works well (once you get the right express modules loaded).

The downside is that you have to write some Javascript of course.

How do you use a bunch of atd files in dune without writing one rule for each file?

Of course writing jbuild files by hand will never be expressive enough. I generate one rule for each file, like this

1 Like

Of course writing jbuild files by hand will never be expressive enough. I generate one rule for each file, like this

Never say never - I think the promote feature from Dune PR#402 and #421 due to be released in Jbuilder beta17 will be of interest here?

I think most people don’t commit the _j and _t files. But I guess it’s a behavior that can be changed. Thanks for the links.