Want to take your software engineering career to the next level? Join the mailing list for career tips & advice Click here


OCaml promises and concurrent I/O.

Subscribe to updates I use lwt

Statistics on lwt

Number of watchers on Github 250
Number of open issues 78
Average time to close an issue about 2 months
Main language OCaml
Average time to merge a PR 8 days
Open pull requests 33+
Closed pull requests 24+
Last commit over 2 years ago
Repo Created about 7 years ago
Repo Last Updated over 2 years ago
Size 11.7 MB
Homepage https://ocsigen.o...
Organization / Authorocsigen
Latest Release3.3.0
Page Updated
Do you use lwt? Leave a review!
View open issues (78)
View lwt activity
View on github
Book a Mock Interview With Me (Silicon Valley Engineering Leader, 100s of interviews conducted)
Software engineers: It's time to get promoted. Starting NOW! Subscribe to my mailing list and I will equip you with tools, tips and actionable advice to grow in your career.
Evaluating lwt for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

Lwt    version 3.3.0 LGPL Gitter chat Travis status AppVeyor status

Lwt is OCaml's concurrent programming library. It provides a single data type: the promise, which is a value that will become determined in the future. Creating a promise spawns a computation. When that computation is I/O, Lwt runs it in parallel with your OCaml code.

OCaml code, including creating and waiting on promises, is run in a single thread by default, so you don't have to worry about locking or preemption. You can detach code to be run in separate threads on an opt-in basis.

Here is a simplistic Lwt program which requests the Google front page, and fails if the request is not completed in five seconds:

let () =
  let request =
    let%lwt addresses = Lwt_unix.getaddrinfo "google.com" "80" [] in
    let google = Lwt_unix.((List.hd addresses).ai_addr) in

    Lwt_io.(with_connection google (fun (incoming, outgoing) ->
      let%lwt () = write outgoing "GET / HTTP/1.1\r\n" in
      let%lwt () = write outgoing "Connection: close\r\n\r\n" in
      let%lwt response = read incoming in
      Lwt.return (Some response)))

  let timeout =
    let%lwt () = Lwt_unix.sleep 5. in
    Lwt.return None

  match Lwt_main.run (Lwt.pick [request; timeout]) with
  | Some response -> print_string response
  | None -> prerr_endline "Request timed out"; exit 1

(* ocamlfind opt -package lwt.unix -package lwt.ppx -linkpkg -o request example.ml
   ./request *)

In the program, functions such as Lwt_io.write create promises. The let%lwt ... in construct is used to wait for a promise to become determined; the code after in is scheduled to run in a callback. Lwt.pick races promises against each other, and behaves as the first one to complete. Lwt_main.run forces the whole promise-computation network to be executed. All the visible OCaml code is run in a single thread, but Lwt internally uses a combination of worker threads and non-blocking file descriptors to resolve in parallel the promises that do I/O.


Lwt compiles to native code on Linux, macOS, Windows, and other systems. It's also routinely compiled to JavaScript for the front end and Node, by js_of_ocaml and BuckleScript.

In Lwt,

  • The core library Lwt provides promises...
  • ...and a few pure-OCaml helpers, such as promise-friendly mutexes, condition variables, and mvars.
  • There is a big Unix binding, Lwt_unix that binds almost every Unix system call. A higher-level module Lwt_io provides nice I/O channels.
  • Lwt_process is for subprocess handling.
  • Lwt_preemptive spawns system threads.
  • The PPX syntax allows using all of the above without going crazy!
  • There are also some other helpers, such as Lwt_react for reactive programming. See the table of contents on the linked manual pages!


  1. Use your system package manager to install a development libev package. It is often called libev-dev or libev-devel.
  2. opam install conf-libev lwt


We are currently working on improving the Lwt documentation (drastically; we are rewriting the manual). In the meantime:

  • The current manual can be found here.
  • Mirage has a nicely-written Lwt tutorial.
  • An example of a simple server written in Lwt.
  • Concurrent Programming with Lwt is a nice source of Lwt examples. They are translations of code from the excellent Real World OCaml, but are just as useful if you are not reading the book.

Note: much of the current manual refers to 'a Lwt.t as lightweight threads or just threads. This will be fixed in the new manual. 'a Lwt.t is a promise, and has nothing to do with system or preemptive threads.


Open an issue, visit Gitter chat, ask in #ocaml, on discuss.ocaml.org, or on Stack Overflow. Please do ask! Even apparently simple questions often end up educating other users, not to mention enlightening the maintainers!

Subscribe to the announcements issue to get news about Lwt releases. It is less noisy than watching the whole repository. Announcements are also made in /r/ocaml, on the OCaml mailing list, and on discuss.ocaml.org.


  • We maintain easy starter issues. These are thoroughly explained and hyperlinked. We hope that this makes working on Lwt accessible even to relative OCaml beginners :)
  • CONTRIBUTING.md contains tips for working on the code, such as how to check the code out, how review works, etc. There is also a high-level outline of the code base.
  • The overall development plan can be found in the roadmap.
  • Ask us anything, whether it's about working on Lwt, or any question at all about it :)
  • The documentation always needs proofreading and fixes.
  • Despite a lot of progress, Lwt still needs more tests.
  • You are welcome to pick up any other issue, review a PR, add your opinion, etc.
  • Any feedback is welcome, including how to make contributing easier!


Lwt is released under the LGPL, with an OpenSSL linking exception. See COPYING.

Related Libraries

  • alcotest A lightweight framework for unit testing

  • angstrom A library for building parsers with a focus on efficiency, concurrency, and reusability

  • cohttp A lightweight library for writing HTTP clients and servers

  • cstruct A library and syntax extension for interop with C-like structures

  • ezjsonm A library for easy interop with JSON

  • faraday A library for fast and memory-efficient serialization

  • logs A logging library with reporting decoupled from logging

  • lwt-parallel A library for distributed computing

  • opium A web toolkit that uses Sinatra-inspired middleware

lwt open issues Ask a question     (View All Issues)
  • almost 4 years Lwt.pick/Lwt.cancel don't cancel certain pending tasks
  • almost 4 years writev support
  • almost 4 years Drop support for 4.01
  • almost 4 years Support NodeJS as a platform
  • about 4 years make `ppx_tools` an optional dep in OPAM
  • about 4 years "Lwt_unix.files_of_directory dir" fails if "dir" can't be read
  • about 4 years Replace establish_server by establish_server_safe
  • about 4 years Lwt_io.shutdown_server should evaluate to a thread
  • about 4 years Lwt_preemptive should provide an "at_exit" for use when a thread ends
  • about 4 years Flaws of Lwt_stream
  • about 4 years Continuous integration meta-issue
  • about 4 years Improve the "optics"
  • over 4 years Subclassing lwt engine doesn't really work.
  • over 4 years Lwt_unix.bind should be in the monad
  • over 4 years Lwt_process.pread/pwrite/with_process_in and friends should (optionally) throw when subprocess exits with a code <> 0
  • over 4 years msvc support
  • almost 5 years Weird interaction between `Unix.create_process` and `Lwt_daemon`/`Lwt_io`
  • almost 5 years Lwt_unix.with_async_switch => longjmp causes uninitialized stack frame => segfault
  • almost 5 years Make the tracing version more available.
  • almost 5 years Inefficient Lwt_io.NumberIO implementations (int32, int64, float read/write).
  • about 5 years Backtraces appear to be broken.
  • about 5 years Lwt_process.exec should support a chdir option
  • about 5 years How to propagate errors with Lwt streams?
  • about 5 years Lwt_process.pread raises Lwt_io.Channel_closed("input") when timed out
  • over 5 years Lwt_stream with several consumers not lwt-threadsafe
  • over 5 years Lwt_log.syslog should not have to look for the syslog socket and just bind to syslog(3). Breaks OS X syslog.
  • over 5 years How to combine Lwt filters?
  • almost 6 years Pooling processes on Windows raised Bad file descriptor (waitpid) error.
  • almost 6 years Interaction between Lwt_daemon and Lwt_preemptive
  • over 6 years Consecutive Lwt_react.E.next calls on an event return the same occurrence.
lwt open pull requests (View All Pulls)
  • Add is_closed and closed operations to Lwt_stream
  • Lwt_preemptive: work around Event.sync perf issue.
  • When using -lpthread, modifying the library search path is harmful
  • Make Lwt compatible with CPS.
  • Avoid deadlock when canceling a thread blocked on a mutex
  • Document opam package `conf-libev`
  • Update examples to use ppx syntax
  • Remove deprecated Lwt_io.of_string, Lwt_sys.windows, Lwt_unix.{run,has_wait4}.
  • add `Lwt_result`
  • Small doc comment update to help address #243
  • Add Lwt_condition.broadcast_exn
  • change close semantics for fixed-length sources
  • Add ?init and ?at_exit to Lwt_preemptive
  • Add support for selecting the libev backend
  • rudimentary module Lwt_opt (RFD, do not pull!)
  • Deprecate Lwt_stream.result
  • writev – zero-copy gather output
  • Test Lwt_io.with_connection at a lower level
  • lwt.ml: human-friendly edition – major refactoring and commenting of the Lwt core
  • Link to Concurrent Programming with Lwt (rwo-lwt)
  • turn a few Lwt_list functions into a tail recursive variant
  • Add Lwt_stream.iter_n
  • Support ;%lwt as sequence syntax -- backwards incompatible in some cases
  • [4.0.0] Switch to new callback deferral semantics
  • [4.0.0] Mark resolvers contravariant
  • [4.0.0] Finish factoring out Camlp4 syntax
  • [4.0.0] Remove >> syntax from the PPX
  • [4.0.0] Complete factoring out the PPX
  • [4.0.0] Delete Lwt_chan
  • [4.0.0] Delete lwt.simple-top
  • Lwt_fmt
  • Link Lwt-related libraries in README.md
  • [5.0.0] Lwt.pick, etc raise Invalid_argument on empty list
lwt questions on Stackoverflow (View All Questions)
  • OCaml profiling lwt
  • How the LWT- Light Weight Transaction is working when we use IF NOT EXIST?
  • How to combine Lwt filters?
  • MAMP Localhost not working (Error 500) - LWT
  • Lwt leaking file descriptors, not sure if bug or my code
  • Canceling a Lwt. thread
  • OCaml lwt utop infix bind operator >>= is missing
  • Redirecting Lwt channels
  • Light Weight Transactions (LWT) failing while new nodes join cluster
  • How to use Lwt with Labltk?
  • opam fails trying to install lwt looking for pthreads
  • Ocaml Lwt - some implementations of multiplayer game
  • Working with ocaml Lwt sockets
  • Why is this Lwt based and seemingly concurrent code so inconsistent
  • How to correctly start a process from a specific directory with Lwt
  • Lwt and recursive functions
  • Lwt and database access
  • Cassandra LWT reads
  • Should we use Cassandra NoSQL counter or LWT for auto incremental integer key generation?
  • Using Core and Lwt together
  • How can I use a Lwt library from Async code?
  • The broker does not deliver the LWT message?
  • How to stop receiving LWT retained message?
  • The server DISCONNECT and I receive LWT message?
  • How to install Cohttp with lwt support?
  • How to make something lwt supported?
  • How to enable syntax color and indention for lwt in Emacs Tuareg mode?
  • How to fully utilise `lwt` in this case
  • Ocaml error lwt
  • Ocaml lwt symbols
lwt list of languages used
lwt latest release notes
3.3.0 Lwt 3.3.0, Lwt_ppx 1.1.0

Bugs fixed

  • Restore backtrace support in the PPX (#554, #556, Gabe Levi).
  • Serious logic error that could cause Lwt to hang or crash (#549, reported @koen-struyve).
  • All Lwt_list functions are now tail-recursive (#538, Joseph Thomas).


  • Support ;%lwt syntax in the PPX (#307, Hezekiah Carty).
  • Lwt_stream.iter_n (#312, Hezekiah Carty).


  • Testing improvements (#536, #541, @cedlemo).
  • Documentation improvements (#544, #546, #547, #553, #559, Daniil Baturin, Jason Evans, Jess Smith, Milo Turner).
3.2.1 Lwt_ppx 1.0.1, Lwt 3.2.1

Lwt 3.2.1 is released because it still packages lwt.ppx, a deprecated copy of package lwt_ppx, and the two packages should be kept in sync.


  • All PPX options are deprecated and should not be used (#534).
  • The [%lwt ...] PPX syntax should be replaced by Lwt.catch (#534).


  • Clean up PPX -help usage message output (#525, Zan Doye).


  • More thorough testing (#512, #535, Joseph Thomas).
  • Clarification of the C binding (#521, @cedlemo).
3.2.0 Lwt 3.2.0


Bugs fixed

  • Lwt.npick never worked (#447, Zack Coker).
  • Lwt_pool.use now always calls ?validate on elements (#461, Joe Thomas).
  • Better locations generated by the PPX (#470, Fabian Hemmer).
  • Keep worker thread count accurate in Lwt_unix when pthread_create fails (#493, @koen-struyve).
  • Leaked exceptions in Lwt_list (#499).
  • Memory leak in Lwt_unix.getnameinfo (#503, Hannes Mehnert).

Planned to break in 4.0.0

See #453 for details and instructions about planned breakage in Lwt 4.0.0.

  • The semantics of Lwt will be adjusted for better exception and stack safety (#500).
  • The PPX will be factored out into its own opam package, lwt_ppx. This package is installable from opam now, as of Lwt 3.2.0 (#338).
  • Similarly, the deprecated Camlp4 syntax will be factored out into lwt_camlp4, which is installable from opam now (#370).
  • Modules Lwt_log, Lwt_log_core, Lwt_log_rules, and Lwt_daemon are being deprecated and factored out into opam package lwt_log, also installable from opam now. Use the logs library for logging, in particular module Logs_lwt. Direct daemonization is deprecated on most platforms (#484, Hannes Mehnert).
  • The >> construct from the PPX will be deleted (#471, Raphal Proust).
  • Package lwt.preemptive is being merged into lwt.unix. In 3.2.0, lwt.preemptive becomes an alias for lwt.unix, and the package name lwt.preemptive will be deleted in 4.0.0 (#487).



  • Replace references to Camlp4 in the manual with the PPX (#457, Bobby Priambodo).
  • More tests for Lwt_pool (#464, Joe Thomas).
  • Expect tests for the PPX (#474, Fabian Hemmer).
Other projects in OCaml