> ## Documentation Index
> Fetch the complete documentation index at: https://launchdarkly.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Using the Lua SDK with HAProxy

This topic explains how to use our [Lua server-side SDK](https://github.com/launchdarkly/lua-server-sdk) with [HAProxy](https://www.haproxy.org/). You can use HAProxy with LaunchDarkly to implement dynamic rate limiting, access controls, rollout, and many other features at the edge of your application architecture.

You can extend HAProxy with [Lua 5.3](https://www.lua.org/manual/5.3/), enabling complex control of [HAProxy functionality](https://www.arpalert.org/src/haproxy-lua-api/3.2/index.html). HAProxy has substantial [commercial adoption](https://www.haproxy.org/they-use-it.html).

Find a basic Dockerized app in the GitHub repository at [hello-haproxy](https://github.com/launchdarkly/hello-haproxy).

## Prerequisites

To complete this guide, you must have the following prerequisites:

* Basic working knowledge of the LaunchDarkly [Lua server-side SDK](/docs/sdk/server-side/lua)
* Basic working knowledge of the LaunchDarkly [C++ server-side SDK](/docs/sdk/server-side/c-c--)

The C++ server-side SDK is required because the Lua server-side SDK is implemented as a wrapper around the C++ server-side SDK.

## Preparing the C++ server-side SDK

Make the binary of the C++ server-side SDK accessible to the dynamic linker. The most convenient way to do this is to install the binary system-wide at `/usr/lib/libldserverapi.so`.

## Ensuring correct initialization

The most important part of effective SDK usage is managing the lifetime of clients correctly. When HAProxy utilizes process-based concurrency, multiple clients initiate. If you accidentally initiate a client per request, the application is substantially slower because the SDK has to download a fresh ruleset from LaunchDarkly.

For ideal operations, initialize each HAProxy worker process exactly once. You can do this with the `lua-load` directive under `global`. This directive executes a script when a process is freshly spawned. Client initialization should reside in this script. In the example below, this file is called `shared.lua`.

Here is an example of initialization logic:

```lua title="Lua SDK v2" lines wrap theme={null}
local ld = require("launchdarkly_server_sdk")
local os = require("os")

return ld.clientInit(os.getenv(sdk_key), 1000, config)
```

```lua title="Lua SDK v1.x" lines wrap theme={null}
local ld = require("launchdarkly_server_sdk")
local os = require("os")

local config = {
    key = os.getenv("YOUR_SDK_KEY")
}

local client = ld.clientInit(config, 1000)
```

Later we can use the result of this initialization process in other services:

```lua title="Lua SDK v2" lines wrap theme={null}
core.register_service("launchdarkly", "http", function(applet)
    applet:start_response()

    local context = ld.makeContext({
        user = {
          key = "abc"
        }
    })

    if client:boolVariation(context, os.getenv(flag_key), false) then
        applet:send("<p>feature launched</p>")
    else
        applet:send("<p>feature not launched</p>")
    end
end)
```

```lua title="Lua SDK v1.x" lines wrap theme={null}
core.register_service("launchdarkly", "http", function(applet)
    applet:start_response()

    local user = ld.makeUser({
        key = "abc"
    })

    if client:boolVariation(user, os.getenv("example-flag-key"), false) then
        applet:send("<p>feature launched</p>")
    else
        applet:send("<p>feature not launched</p>")
    end
end)
```

<View title="Developer">
  > [!NOTE]
  >
  > **Want to know more? Start a trial.**
  >
  > Your 14-day trial begins as soon as you sign up. Get started in minutes using the in-app Quickstart. You'll discover how easy it is to release, monitor, and optimize your software.\
  > \\
  >
  > Want to try it out? [Start a trial](https://app.launchdarkly.com/signup).
</View>

<View title="Federal docs" />

<View title="EU docs" />
