Here are comments from somebody who "knows C++" but does not know a lot about NW and has read only the 1st https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/asi... page. // get iterators representing the range of characters in the buffer auto begin = range::begin(buffer.data()); auto end = range::end(buffer.data()); Quite a weird pattern, where buffer does not have member begin, end. Maybe a sentence or two describing the rationale and complexity would be nice. I know it is O(1), but it is weird that begin/end are called on pointer. std::size_t read_lineI am tired, but is this function O(n^2)? cb += bytes_transferred; // adjust the pointer and sizeI would maybe switch to write instead of write_some to keep the code shorter, and mention write_some as another option in text. [](error_code ec, std::size_t bytes_transferred) For learning purposes I would capture something in lambda by value and note that reference capture would be buggy. using type = std::allocator<void>; Personal preference: not a fan of typedefs for relatively short types used once. All in all nice intro, unfortunately it requires users to understand templates quite well, but honestly not sure if it is avoidable, with a gazillion customization points in ASIO.