|  | # Zircon Kernel IPC Limits | 
|  |  | 
|  | ## Introduction | 
|  |  | 
|  | The Zircon API is asynchronous for both sending and receiving. It requires that kernel buffers | 
|  | data on behalf of the senders until receivers can drain it. If the total rate of sending data | 
|  | is greater than the rate of reading the data over an extended period of time system can run out | 
|  | of kernel buffers to service even critical tasks. | 
|  |  | 
|  | The experience is that for asynchronous systems that (in very rare occasions) return error codes | 
|  | such as "try again", the application handling code is rarely correct; these paths are hard to test | 
|  | and hard to get right: in particular the simple treatment of retry in a loop converts an | 
|  | asynchronous service into a synchronous service, leading to livelocks and deadlocks. | 
|  |  | 
|  | Instead, when programming for Zircon, developers should assume that sending IPC messages at a | 
|  | reasonable rate in a healthy system always succeeds. The kernel in turn implements some limits on | 
|  | the amount of data it can buffer and when the limit is crossed, a | 
|  | [policy exception](/docs/concepts/kernel/exceptions.md) is raised in the calling thread for the | 
|  | following syscalls: | 
|  |  | 
|  | - [`zx_channel_write()`] | 
|  | - [`zx_channel_write_etc()`] | 
|  | - [`zx_port_queue()`] | 
|  |  | 
|  | The precise limits are enforced per each instance of a kernel object and are not disclosed in the | 
|  | form of constants to applications to prevent code from depending on these limits, which can be | 
|  | further modified by product-specific considerations. | 
|  |  | 
|  | It is not expected that the application or library handles the exception; in most cases the | 
|  | appropriate action so to let the exception propagate to the crash analysis service. | 
|  |  | 
|  | ## Strategies to Avoid IPC Limits | 
|  |  | 
|  | At a high level the main strategy is to equalize the rate of buffers being added and being drained | 
|  | from each pair of consume and producer. There are many possible schemes such as flow control, | 
|  | request/response, request-expiration, sidecar VMOs, etc. The most appropriate method depends | 
|  | on the nature of the service. | 
|  |  | 
|  |  | 
|  | [`zx_channel_write()`]: /docs/reference/syscalls/channel_write.md | 
|  | [`zx_channel_write_etc()`]: /docs/reference/syscalls/channel_write_etc.md | 
|  | [`zx_port_queue()`]: /docs/reference/syscalls/port_queue.md | 
|  |  |