Contrary to the kernel space, the user space is a higher-level portion of the OS where user-facing applications and processes run. This doesn't strictly refer to the graphical portion of the system, but also describes the separate virtual memory space allocated to these programs. GUI and CLI interactions are still hallmarks of the user space.
Also called "userland," the user space has reduced privileges vs. the kernel space and acts like a sandbox. Its code operates at ring 3 — where browsers, games, and productivity applications run, to name a few examples. In fact, ring 3 is the least trusted layer within x86 architectures. The kernel space's processes are thus abstracted away and largely isolated from the user space.
However, the user space can make system calls to the kernel when (safe) privilege escalation is needed. The libc library often serves as a bridge between these two environments by facilitating function calls to the kernel. Users also don't have to trigger all processes manually. The OS will start and stop critical processes in the background during runtime (such as daemon processes) — including at the beginning of a session upon startup.
User spaces and their processes will naturally vary from one OS to another. For example, a given process in Linux might be named differently or function differently from one in Unix. Underlying user space processes might also change depending on application deployment model, such as VMs or containers.
What makes the user space useful?
First, the user space stands separate due to security reasons. By restricting the processes and resources the user space can access, the OS can protect itself from system crashes and vulnerabilities stemming from user-facing applications.
Applications, daemons, and more have the memory/CPU they need to run smoothly, while core OS stability isn't impacted. These protections are applicable to both legitimate and malicious processes. The kernel is generally better at closely managing these allocations.
Finally, it's easier to develop new applications in the user space than in the kernel space. Not only is the kernel more locked down, but the user space offers better compatibility with a variety of programming languages (plus supported libraries).
How does HAProxy interact with the user space?
HAProxy lives in the user space and takes connections from the kernel space (generally via epoll), receives the requests, calculates and negotiates TLS as needed, and decides where to route the request. It may also tell the kernel space to connect to a chosen backend IP and send the requests there — keeping the backend connection in a pool for future requests. Optionally, HAProxy can evaluate requests and tell the kernel to stop processing them.
Once the backend responds, HAProxy will usually call the splice system call — harnessing the client's network buffer for forwarding without copying the data through the user space (unless it's required).