# Your production web stack in 2020

**URL:** <https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691>\
**Category:** Ecosystem\
**Created:** [November 1, 2020, 7:21pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691 "2020-11-01T19:21:10Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [November 1, 2020, 7:21pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/1 "2020-11-01T19:21:10Z")

</div>

Hey folks, especially those running web back-ends and front-ends in OCaml/Reason: what is your stack?

> There has been a similar question [previously](https://discuss.ocaml.org/t/could-you-please-describe-your-stack-for-web-apps-development-in-ocaml-with-reasoning-about-it/1422), however, two years is a long time, so, maybe, things have changed since then.

In particular:

Back end:

- Database, database driver, migrations, any other database-access layer, for example, a ppx
- Web server and framework
- Concurency library (Lwt/Async)
- Any other thing worth mentioning, like ocaml-graphql-server

Front end:

- Transpiler: Js\_of\_ocaml or ReScript (BuckleScript)
- Framework
- Concurrency library (Lwt/Async/JS Promises)

I’m asking because I’m curious to see which combinations of these technologies are battle-tested. Certain kinds of issues only arise (and get solved) when used at certain scale. It’s also interesting what combinations of technologies work well together. For example, httpaf+async appears like a well tested path, while httpaf+lwt seems like more experimental (my guess). Or, for example, caqti+lwt seems like a tried path, while caqti+async might not be.

To share my experience, I’ve made some prototypes using Windows+Cohttp+Lwt on the back end and Linux+BuckleScript+ReasonReact+JS promises on the front end, but I can’t judge about the robustness of the solution. Certainly there was a lot of friction when trying to share the code between the two “ends”. Like writing it in two different languages. Which is now sort of acknowledge with ReScript becoming a fork of OCaml.

Looking forward to hear about your experiences!

---

<div class="post-metadata">

**Author:** ![anuragsoni](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/anuragsoni/32/1107_2.png) [@anuragsoni](https://discuss.ocaml.org/u/anuragsoni)\
**Post date:** [November 1, 2020, 8:30pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/2 "2020-11-01T20:30:39Z")

</div>

At day job:

- Database: Postgresql (driver: pgx [https://opam.ocaml.org/packages/pgx\_async/](https://opam.ocaml.org/packages/pgx_async/))
- Web server: cohttp-async ([https://opam.ocaml.org/packages/cohttp-async/](https://opam.ocaml.org/packages/cohttp-async/)) for the server implementation
- Misc:
  1. Routes ([https://opam.ocaml.org/packages/routes/](https://opam.ocaml.org/packages/routes/)) for web-routing
  2. [https://opam.ocaml.org/packages/sentry/](https://opam.ocaml.org/packages/sentry/) for reporting errors
  3. [https://github.com/arenadotio/ocaml-statsd-client](https://github.com/arenadotio/ocaml-statsd-client) for metrics reporting to datadog
  4. logs ([https://opam.ocaml.org/packages/logs/](https://opam.ocaml.org/packages/logs/)) for logging (we push the logs to datadog).
  5. atd ([https://opam.ocaml.org/packages/atd/](https://opam.ocaml.org/packages/atd/)) for json serialization and deserialization

- Concurrency Library: Async

For personal projects:

- Database: Postgresql with a very [WIP ocaml client](https://github.com/anuragsoni/postgres-protocol)
- Web Server:
  1. httpaf-async ([https://opam.ocaml.org/packages/httpaf-async/](https://opam.ocaml.org/packages/httpaf-async/) + an async\_ssl wrapper)
  2. Routes library for routing layer.

- Concurrency Library: Async

I’ve been really happy using Async and most of my work still uses it since core + async is an ecosystem I’m most familiar with. I really like async’s monitors (probably my favorite part of the library), and the consistent experience that one gets when using the various libraries from the Janestreet ecosystem (I’m really grateful for all the open source work coming out of Janestreet, as I benefit a lot from it).

Do note that while most of my list is libraries from the async side of ecosystem, I’ve been experimenting with Lwt recently as i’m really interested in the mirage ecosystem so my set of preferred libraries might change over time as I start writing more mirage unikernels 😄

---

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [November 2, 2020, 12:01pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/3 "2020-11-02T12:01:34Z")

</div>

@anuragsoni looks interesting! Do you use anything for DB connection pooling?

---

<div class="post-metadata">

**Author:** ![Drup](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/drup/32/35_2.png) [@Drup](https://discuss.ocaml.org/u/Drup)\
**Post date:** [November 2, 2020, 12:28pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/4 "2020-11-02T12:28:22Z")

</div>

Eliom  
That’s the whole stack  
ᕙ( •̀ ◡ •́ )ᕗ

---

<div class="post-metadata">

**Author:** ![anuragsoni](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/anuragsoni/32/1107_2.png) [@anuragsoni](https://discuss.ocaml.org/u/anuragsoni)\
**Post date:** [November 2, 2020, 12:50pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/5 "2020-11-02T12:50:18Z")

</div>

@keleshev I haven’t landed on a connection pooling solution for an async Postgres client at the moment (for lwt I think ocsigen project has a resource pool library that can be plugged in very easily).

My goal is to work towards contributing a new driver for caqti so I can benefit from connection pooling and other features caqti provides while still being able to use a pure OCaml Postgres client.

In the meantime I’d lean towards a solution like pgbouncer ([https://www.pgbouncer.org/usage.html](https://www.pgbouncer.org/usage.html)) that can handle session level connection pooling for Postgres.

---

<div class="post-metadata">

**Author:** ![kanishka](https://avatars.discourse-cdn.com/v4/letter/k/3e96dc/32.png) [@kanishka](https://discuss.ocaml.org/u/kanishka)\
**Post date:** [November 2, 2020, 4:01pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/6 "2020-11-02T16:01:07Z")

</div>

Your observability is pretty thorough. Are you looking at open telemetry or honeycomb next?

---

<div class="post-metadata">

**Author:** ![anuragsoni](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/anuragsoni/32/1107_2.png) [@anuragsoni](https://discuss.ocaml.org/u/anuragsoni)\
**Post date:** [November 2, 2020, 4:42pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/7 "2020-11-02T16:42:05Z")

</div>

No plans at looking at these at the moment.  
Honeycomb looks interesting. I wasn’t aware of them so thanks for pointing that out!

---

<div class="post-metadata">

**Author:** ![Khady](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/khady/32/469_2.png) [@Khady](https://discuss.ocaml.org/u/Khady)\
**Post date:** [November 2, 2020, 5:06pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/8 "2020-11-02T17:06:43Z")

</div>

Backend side:

- lwt
- httpev (from devkit), routes, atdgen + some code generation to generate a typed web server and http clients (bucklescript and native) from a specification
- slowly getting tyxml in for static and correct html generation
- ocaml-mysql + sqlgg, elasticsearch + esgg, redis as databases
- extprot as a serialization format for a lot of internal data exchange or storage
- log and logstash (from devkit) for logging and monitoring
- web (from devkit) as an http client on top of ocurl
- mostly ounit and dune expect tests for testing

Frontend side (subject to change in the future)

- bucklescript + reason react
- bindings to a lot of different libs for specific usage (less “original” code that is not product specific)

The main benefit of all this code is that we can have types that are propagated from the DB to the frontend through the web server, thanks to everything being written in ocaml.

---

<div class="post-metadata">

**Author:** ![Haudegen](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/haudegen/32/716_2.png) [@Haudegen](https://discuss.ocaml.org/u/Haudegen)\
**Post date:** [November 2, 2020, 9:50pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/9 "2020-11-02T21:50:17Z")

</div>

Backend:

- Webmachine (Cohttp)
- Lwt
- Postgresql-ocaml, Ezpostgresql
- Yojson
- Xmlm
- Jingoo
- Csv, Csv-lwt
- Netclient (email)
- Safepass

Frontend: Vue.js

REST-clients: Cohttp.

---

<div class="post-metadata">

**Author:** ![smondet](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/smondet/32/111_2.png) [@smondet](https://discuss.ocaml.org/u/smondet)\
**Post date:** [November 3, 2020, 3:14pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/10 "2020-11-03T15:14:54Z")

</div>

Not my “full-2020-stack” but I just deployed the port of [https://tqtezos.github.io/TZComet/](https://tqtezos.github.io/TZComet/) from Tyxml\_js/React/ReactiveData to Tyxml-lwd from @let-def

- cf. [https://github.com/let-def/lwd](https://github.com/let-def/lwd) — OCaml 2020 had a talk about Nottui/Lwd
- it’s a client-side-only JSOO app, but it can talk to public Tezos nodes, so technically the “backend” is Cohttp/Lwt-based likely behind nginx-like proxies.

Pretty happy with `Tyxml_lwd`:

- I initially hit a couple of bugs, that @let-def fixed very fast (I think I was the first bigger user).
- It is overall not _that_ different from the `Tyxml_js` combo, but the API is simpler and feels way cleaner:
  - there is no “reactiveData” awkward middle-person (or let’s say its equivalent is better integrated in the Lwd case)
  - there are less (no?) traps with `React.S.value` throwing exceptions or `==` equality being used in subtle ways
  - There is no `Tyxml_js.Html` Vs `Tyxml_js.Html.R` distinction, which makes it easier to build nicer UI abstractions on top of HTML.
  - Bonus points for **`let empty () = Lwd.pure Lwd_seq.empty`** and  
**`let ( % ) a b = Lwd.map2 ~f:Lwd_seq.concat a b`**  
allowing me to have an efficient and very practical “HTML monoid” interface.

---

<div class="post-metadata">

**Author:** ![lepoetemaudit](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lepoetemaudit/32/2183_2.png) [@lepoetemaudit](https://discuss.ocaml.org/u/lepoetemaudit)\
**Post date:** [November 3, 2020, 4:37pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/11 "2020-11-03T16:37:57Z")

</div>

Not exactly a full web stack as it’s essentially a REST API I’m working on, but:

Backend:

- Httpaf
- Lwt
- pgocaml (with the ppx)
- Yojson
- Cohttp (HTTP client)
- amqp
- redis-lwt

Routing etc., is handled by internal libs wrapping Httpaf, I developed some functor and ppx stuff for defining an OpenAPI HTTP server in a type safe and declarative way so it’s pretty specialised.

Frontend (for internal utilities and prototyping):

- js\_of\_caml
- ocaml-vdom

---

<div class="post-metadata">

**Author:** ![rizo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rizo/32/93_2.png) [@rizo](https://discuss.ocaml.org/u/rizo)\
**Post date:** [November 4, 2020, 12:09pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/12 "2020-11-04T12:09:22Z")

</div>

### Backend

- **opium** - Currently using master (includes httpaf) with a couple of custom unpublished modifications. Overall I’m happy with how simple it is and like the direction of the project. Many auxiliary utilities for session, migrations, auth management are still missing.
- **sqlgg** - Takes care of generating DB management modules based on SQL schema. A very nice tool when it works. The error messages are pretty confusing sometimes and there are some limitations with NULL handling in generated queries. Highly recommend this approach for projects with simple models.
- **yojson** / **cstruct** / **csv** - we work with both binary and textual formats in our APIs. These are some of the serialisation packages we currently use. Very reliable overall. Recently started using [BARE](https://github.com/c-cube/bare-ocaml) which is a bit more experimental.
- **coap** (unpublished) - An HTTP-like protocol for constrained/embedded devices. We wrote our own implementation and have been testing it for a few month now.
- **mqtt-client** (unpublished) - used to sync real-time data between our servers. The implementation is a bit incomplete but has been working reliably.
- **irmin** - used for long-term distributed storage of our time-series events.
- **swagger** - used to generate a specification for our API. The integration is still work in progress, but it’s nice to be compatible with standard tooling.

### Frontend

- **ReasonReact** - provides a very solid development experience, but we have been recently considering switching to something based on js\_of\_ocaml. Not only I’m somewhat confused by the latest ReScript changes, but also need to share some small libraries between the backend and the frontend.
- **Sx** (unreleased) - a custom CSS-based styling library inspired by [https://tailwindcss.com](https://tailwindcss.com).

---

<div class="post-metadata">

**Author:** ![Konstantin\_Olkhovski](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/konstantin_olkhovski/32/1494_2.png) [@Konstantin\_Olkhovski](https://discuss.ocaml.org/u/Konstantin_Olkhovski)\
**Post date:** [November 4, 2020, 2:44pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/13 "2020-11-04T14:44:25Z")

</div>

Backend:

- Cassandra as a database (unpublished bindings to DataStax cpp driver’s C API along with unpublished ppx for type safe code generation)
- In-house Httpaf based (we use fork by @anmonteiro) HTTP framework specialized for the way we work with microservices (framework also supports node.js platform, but bypassess Httpaf and uses node.js HTTP API directly for performance)
- Routes for HTTP routing
- Lwt for concurrency library
- stdlib: Core for native/Core\_kernel for jsoo
- atdgen for API types, sometimes yojson directly
- prometheus ([https://github.com/mirage/prometheus](https://github.com/mirage/prometheus)) for metrics reporting
- logs ([https://github.com/dbuenzli/logs](https://github.com/dbuenzli/logs)) for logging
- alcotest, ppx\_expect, ppx\_inline\_tests for tests
- crowbar for fuzzing

CI:

- opam-bin greatly helps speed up our CI pipelines, and beats caching `_opam` folder in our environment

Frontend:

- BuckleScript with Reason (trying to figure out what the hack we should do with this ReScript story…)
- React as a framework
- JS promises for concurrency

The most challenging part of building all this was Httpaf-based framework. We started with vanilla Httpaf, forked Lwt adapter to bring in TLS and some other features. Our adapter did not work really well (it was quickly hacked together), and we stumbled upon some bugs in Httpaf that manifested in our peculiar use case (storage systems). Then we tried Antonio’s fork, which had those bugs fixed, and found some new bugs there 😃 Many thanks to @anmonteiro, all bugs were sorted out really fast! We wouldn’t be able to push our HTTP framework to a usable state without his work and help. So far everything works pretty stable and we have a service on this stack running in production.

---

<div class="post-metadata">

**Author:** ![ruyblast](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ruyblast/32/1897_2.png) [@ruyblast](https://discuss.ocaml.org/u/ruyblast)\
**Post date:** [November 4, 2020, 3:27pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/14 "2020-11-04T15:27:38Z")

</div>

All with eliom too 🙂 (with integrated pgocaml, js\_of\_ocaml and lwt). I use also nginx as a reverse proxy (mainly for TLS), and I use Foundation as a css framework (I find it really above others I tried before).

---

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [November 5, 2020, 8:46pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/15 "2020-11-05T20:46:32Z")

</div>

I’m overwhelmed by all responses in this thread, I think all of these setups are super interesting and each of them deserves a blog post or something!

---

<div class="post-metadata">

**Author:** ![roddy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/roddy/32/2261_2.png) [@roddy](https://discuss.ocaml.org/u/roddy)\
**Post date:** [November 5, 2020, 10:39pm UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/16 "2020-11-05T22:39:26Z")

</div>

This is for a privateish personal project with a couple of hundred users. I’ve not been working on it in the past couple of months but it’s still in use.

Backend:  
Database - Postgres/caqti/ppx\_rapper  
Framework - master opium with httpaf, [my own framework](https://github.com/roddyyaga/ocoi/) on top of that (not sure it is stable enough to recommend for others currently)  
Stdlib - core  
Concurrency - Lwt  
Other - In this project I also use [aws-s3](https://github.com/andersfugmann/aws-s3), and [my own HTTP client library](https://github.com/roddyyaga/quests/) (based on cohttp) for things like connecting to slack and email sending APIs (although for the latter I would use [letters](https://github.com/oxidizing/letters) if starting from scratch again, I just couldn’t find a sufficiently easy to use lwt SMTP client when I began). In other projects I’ve used ocaml-websocket, which seems good. For the first project, I send web push notifications by shelling out to a Python script; this is almost possible to do in OCaml but just needs an implementation of ECDSA in a crypto library.

Frontend: ReScript (with Reason (not ReScript) syntax) and ReasonReact. I think it is very useful to share types (or slightly more, I have experimented with sharing specifications of REST endpoints) between frontend and backend, and rarely useful to share significant amounts of logic. For apps where this is true I definitely like ReScript over Js\_of\_ocaml, especially if you are doing a reasonable amount of JS interop. I use yojson on the frontend as well as the backend, but in hindsight this is probably a bit silly and isn’t required to share type definitions (would be better to use decco instead). I wrote [some bindings](https://github.com/roddyyaga/bs-swr) to SWR which I think is nice. Just use the builtin stdlib, I don’t find anything more to be necessary for the kind of frontend stuff I’m doing.

Deployment:  
Backend - a few server processes in individual docker containers, behind (also dockerized) nginx. Postgres also in docker (possibly not necessary).  
Frontend - nginx in docker.  
Everything runs on one VPS, deployed/managed with ansible and bash. I do various admin tasks from a docker container with `dune utop` for the project.

---

<div class="post-metadata">

**Author:** ![hcarty](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hcarty/32/1824_2.png) [@hcarty](https://discuss.ocaml.org/u/hcarty)\
**Post date:** [November 6, 2020, 5:54am UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/17 "2020-11-06T05:54:05Z")

</div>

Like a few others here, my projects have been more backend/API focused, so very little frontend code to speak of. It’s mostly internal systems talking to one another to form data pipelines.

- opam, dune, latest OCaml, stdlib, Lwt, yojson, cmdliner and a handful of other libraries as the base
- cohttp with a custom routing, logging, query parsing layer for servers (to be released when I can make time to package it properly)
- cohttp via [ezrest](https://github.com/hcarty/ezrest) for clients
- ocaml-mysql via [ezmysql](https://github.com/hcarty/ezmysql) talking to mariadb when a relational database is needed. [Mwt](https://github.com/hcarty/mwt) helps bridge the concurrency gap between ocaml-mysql and Lwt
- Elasticsearch for lots of things
- [logs](https://github.com/dbuenzli/logs) for logging, rendered to JSON and shipped to Elasticsearch
- alcotest, mdx and ppx\_expect for tests
- Services are built + deployed in containers on Linux, bare VMs when running on Windows
- Internal command line tools our team and those around us are built as native binaries for Linux, WIndows, macOS

---

<div class="post-metadata">

**Author:** ![mro](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mro/32/2496_2.png) [@mro](https://discuss.ocaml.org/u/mro)\
**Post date:** [November 6, 2020, 8:05am UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/18 "2020-11-06T08:05:20Z")

</div>

writing personal mini-services scaling towards n=1, I do

- CGI “on the metal” (env+stdio)
- deliver raw data (e.g. gpx)
- make nice in the browser via xslt and require no Javascript.

e.g. [https://demo.mro.name/geohash.cgi](https://demo.mro.name/geohash.cgi)

P.S.: Doing https requests on arm/linux would be nice. Currently painful.

---

<div class="post-metadata">

**Author:** ![lambdam](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lambdam/32/2053_2.png) [@lambdam](https://discuss.ocaml.org/u/lambdam)\
**Post date:** [November 6, 2020, 8:53am UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/19 "2020-11-06T08:53:50Z")

</div>

Hello,

I am mainly a Clojure developer in my professional life but am very interested  
in OCaml for quite some time.

I am interested in the question of web development also for a long time and here  
are my impressions:

1. Ocsigen seems, from the “outside world”, to be the goto solution for web  
development in OCaml but I’m surprised to see nobody using it. If I get it  
well, using Eliom is not using the whole package of Ocsigen.
2. The whole OCaml ecosystem seems to switch to `dune`. When I read the docs of  
Ocsigen, it’s full of `Makefile` commands. Is it to understand that Ocsigen  
is behind the trend in terms of “modernness”?
3. By reading the answers, I understand that many people use their own set of  
small plugable libraries (this is actually what people do in the Clojure  
ecosystem where there is no fullstack framework at all). Is it the common way  
of doing web development in the OCaml community nowadays?

With Clojure, we are very used to REPL based programming. At dev time, we often  
use libraries that implement the “Reloaded workflow”. It is a system/dependency  
injections approach. At dev time it enables one to start the system with proper  
stateful dependencies (like database) and the cleanly stop the system, reload  
the code and restart the system. Two modern versions of this approach are  
[integrant](https://github.com/weavejester/integrant) and  
[clip](https://github.com/juxt/clip). Is there something similar in the OCaml  
world? Or is it useless due to OCaml compiler speed and some other mechanism  
that handles stateful part cleanly?

Thanks a lot

---

<div class="post-metadata">

**Author:** ![ruyblast](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ruyblast/32/1897_2.png) [@ruyblast](https://discuss.ocaml.org/u/ruyblast)\
**Post date:** [November 6, 2020, 10:48am UTC](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691/20 "2020-11-06T10:48:05Z")

</div>

Hi @Lambdam,

I did not mention it, but I use the whole stack of Ocsigen (from ocsigen-start). Maybe some people are using the term Eliom to talk about ocsigen stack, I am guilty of doing so. I was very little experienced in web development (a bit of js and typescript) when I decided to use it, and I did not try ocaml alternatives so I can not talk about them. I would not have been comfortable with picking and using different libraries, and this standalone framework was perfect to me.  
I had to go through a lot of documentation, maybe for a full-time month (going through tutorials too), but I found it quite clear and written with care, so it was ok. I think when one wants to do something quite specific, it is a bit a pain to go through all the docs to catch the logic, because ocsigen does “everything” (including many things I could not imagine possible ^^). Too me, this is a pro when you want to have a lot of options in one tool (client-server app, cross-platform, reactive programming, elm architecture with vdom…) but a con when you have limited needs that you know will cover your project. I think one who learned to use different libraries over times have a lot of options too of course, but the learning path seems less linear.

Ultimately, when you have to decide where to start, I think it depends of your use case and how much you are familiar with some practice of web programming. Hopefully, the community is very helpful in my experience, I am sure we will help you find a tooling set that suites your need or your expectations.

I do not know what most people are doing, but there are definitely serious industrial players using ocsigen (starting from besport), and it is still under development as far as I know, so it is not “old stuff”. Dune is really a great tool, and I personally would prefer ocsigen-start would build with it. However the Makefile is definitely doing the job right, so I understand they currently focus on other challenges they face (I certainly would do the same choice). I hope some day I will have resources to contribute on this 🙂

For REPL based programming, I know nothing about it, but as you state ocaml compilation is fast (and even faster with dune :o).

I think ocaml is a really good language for the web. I notice some like there type preserved from database storage to front-end, I agree so much on this! To me, web use cases are vast and different, that is why web stacks are heterogeneous (it is the case in most languages). I think all people here present good stacks that met their need. Hope you will find yours and that you enjoy, in ocaml or another language 😉

Best

[Next page](https://discuss.ocaml.org/t/your-production-web-stack-in-2020/6691.md?page=2)
