Performance measurements of network protocols in microkernel systems have been discouraging, typically 2 to 5 times slower than comparable macrokernel systems. This disparity has led many to conclude that the microkernel approach, where protocols reside at user-level, in inherently flawed and that protocols must be placed in the kernel to get reasonable performance. We show that user-level network protocols have performed poorly because they rely on code designed to run in a kernel environment. As a result, they make assumptions about the costs of primitive operations such as scheduling, preemption, and data transfer which can require substantial overhead to satisfy at user level. Good user-level protocol performances can be achieved by restructuring protocol servers to take advantage of microkernel facilities, rather than ignore them.