Un mensaje puede tener derechos de puertos (además de los datos). Esto es muy significativo, pues de esta manera una tarea puede obtener nuevos derechos por el hecho de recibir un mensaje.
Un mensaje consiste de un encabezado de tamaño fijo seguido por la lista de datos que tenga el mensaje. El encabezado especifica el nombre del puerto al cual se le envía el mensaje, el nombre del puerto por el cual se espera la respuesta del mensaje (si la solicitud se contesta), el tamaño del mensaje y los campos de código de operación.
La lista de datos le sigue al encabezado. Cada uno consiste de un descriptor de dato seguido por el dato. El tipo de descriptor especifica el tipo de dato, al igual que un contador de el número de datos en la lista de este tipo.
Un mensaje puede contener referencias a memoria fuera de línea, que se indican en los descriptores de datos, y como las otras partes del mensaje, esta referencia se copia virtualmente del emisor al receptor. El núcleo utiliza una optimización copy-on-write de memoria bastante significativa para pasar datos grandes de una manera eficiente. Para los datos fuera de línea, después del descriptor aparece la dirección virtual del dato, en lugar del dato. Cuando se recibe un mensaje que tiene memoria fuera de línea, esta memoria aparecerá como si se asignara memoria nuevamente, utilizando el mismo manejador de memoria que el emisor utilizó.