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

# Private attributes: Server-side SDKs

> This topic explains how to configure private context and user attributes in LaunchDarkly SDKs. These features are available for client-side, server-side, and AI SDKs. This page covers server-side sdks.

> For the complete documentation index, see [llms.txt](/llms.txt). For the full documentation snapshot, see [llms-full.txt](/llms-full.txt).

## Server-side SDKs

Here are the configuration options for private context and user attributes in server-side SDKs:

* [.NET (server-side)](#net-server-side)
* [Apex](#apex)
* [C++ (server-side)](#c-server-side)
* [Erlang](#erlang)
* [Go](#go)
* [Haskell](#haskell)
* [Java](#java)
* [Lua](#lua)
* [Node.js (server-side)](#nodejs-server-side)
* [PHP](#php)
* [Python](#python)
* [Ruby](#ruby)
* [Rust](#rust)

### .NET (server-side)

<Accordion title="Expand .NET (server-side) code sample">
  In the server-side .NET SDK there are two ways to define private attributes for the entire LaunchDarkly client:

  * When creating the LaunchDarkly `Configuration` object, you can configure [`Events`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Server.ConfigurationBuilder.html#LaunchDarkly_Sdk_Server_ConfigurationBuilder_Events_) with [`AllAttributesPrivate`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Server.Integrations.EventProcessorBuilder.html#LaunchDarkly_Sdk_Server_Integrations_EventProcessorBuilder_AllAttributesPrivate_), which takes in a boolean parameter. If `true`, the SDK removes all attributes for all contexts before sending the context to LaunchDarkly, except the key.
  * Or, you can configure `Events` with [`PrivateAttributes`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Server.Integrations.EventProcessorBuilder.html#LaunchDarkly_Sdk_Server_Integrations_EventProcessorBuilder_PrivateAttributes_), which takes any number of attribute names or slash-delimited paths to designated a JSON property within an attribute, such as `/address/street`. If any context has a custom or built-in attribute that matches one of these names, the SDK removes it before sending the context to LaunchDarkly.

  For example:

  <CodeGroup>
    ```csharp title=".NET SDK v7.0 (C#)" theme={null}
          // All attributes marked as private
          var config = Configuration.Builder("YOUR_SDK_KEY")
              .Events(
                  Components.SendEvents()
                     .AllAttributesPrivate(true)  // defaults to false
              )
              .Build();

          var client = new LDClient(config);

          // Two attributes marked as private
          var config = Configuration.Builder("YOUR_SDK_KEY")
              .Events(
                  Components.SendEvents()
                    .PrivateAttributes("email", "address")
              )
              .Build();

          var client = new LDClient(config);
    ```
  </CodeGroup>

  You can also mark attributes as private when building the context object by calling [`Private()`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.ContextBuilder.html#LaunchDarkly_Sdk_ContextBuilder_Private_) after setting the attribute on the context builder.

  For example:

  <CodeGroup>
    ```csharp title=".NET SDK v7.0 (C#)" theme={null}
          var context = Context.Builder("example-context-key")
              .Set("email", "sandy@example.com")
              .Private("email")
              .Build();
    ```
  </CodeGroup>

  When the SDK sends this context back to LaunchDarkly, it removes the `email` attribute.
</Accordion>

### Apex

<Accordion title="Expand Apex code sample">
  You can configure the Apex SDK to treat some or all user attributes as private user attributes, either using the `LDConfig` object or on a per-user basis.

  When creating the `LDConfig` object, you can use `setAllAttributesPrivate(true)`. When you do this, all user attributes, except the key, are redacted before the SDK sends the user to LaunchDarkly.

  Here's how:

  <CodeGroup>
    ```java title="Java" theme={null}
          LDConfig config = new LDConfig.Builder()
              .setAllAttributesPrivate(true)
              .build();
    ```
  </CodeGroup>

  You can also define private attribute names on a per-user basis:

  <CodeGroup>
    ```java title="Java" theme={null}
          Set<String> privateAttributes = new Set<String>();
          privateAttributes.add('firstName');

          LDUser user = new LDUser.Builder('example-user-key')
              .setFirstName('alice')
              .setPrivateAttributeNames(privateAttributes)
              .build();
    ```
  </CodeGroup>
</Accordion>

### C++ (server-side)

<Accordion title="Expand C++ (server-side) code sample">
  In the C++ SDK there are three ways to define private attributes for the LaunchDarkly client:

  * When creating the config object, you can use `AllAttributesPrivate`. When you do this, the SDK only sends the context key and kind to LaunchDarkly.

    For example:

  <CodeGroup>
    ```cpp title="C++ SDK v3.0 (native)" theme={null}
            auto config_builder = server_side::ConfigBuilder("YOUR_SDK_KEY");
            config_builder.Events().AllAttributesPrivate(true);
            auto config = config_builder.Build();
    ```

    ```c title="C++ SDK v3.0 (C binding)" theme={null}
            /* sets all attributes private */
            LDServerConfigBuilder config_builder = LDServerConfigBuilder_New("example-mobile-key");
            LDServerConfigBuilder_Events_AllAttributesPrivate(config_builder, true);

            LDServerConfig config;
            LDStatus config_status = LDServerConfigBuilder_Build(config_builder, &config);

            /* sets "email" and "address" private */
            LDServerConfigBuilder config_builder = LDServerConfigBuilder_New("example-mobile-key");
            LDServerConfigBuilder_Events_PrivateAttribute(config_builder, "email");
            LDServerConfigBuilder_Events_PrivateAttribute(config_builder, "address");

            LDServerConfig config;
            LDStatus config_status = LDServerConfigBuilder_Build(config_builder, &config);
    ```

    ```c title="C SDK v2.x (native)" theme={null}
            LDConfigSetAllAttributesPrivate(config, true);
    ```
  </CodeGroup>

  * When creating the config object, you can list specific private attributes with `PrivateAttributes`. The SDK removes all attributes in this list before sending the context to LaunchDarkly.

    Here's how:

  <CodeGroup>
    ```cpp title="C++ SDK v3.0 (native)" theme={null}
            auto config_builder = server_side::ConfigBuilder("YOUR_SDK_KEY");
            config_builder.Events().PrivateAttributes({"email"});
            auto config = config_builder.Build();
            if (!config) {
                /* an error occurred, config is not valid */
            }
    ```

    ```c title="C SDK v2.x (native)" theme={null}
            LDConfigAddPrivateAttribute(config, "email");
    ```
  </CodeGroup>

  * You can also define private attributes on a per-context basis. For example:

  <CodeGroup>
    ```cpp title="C++ SDK v3.0 (native)" theme={null}
            auto context = ContextBuilder()
              .Kind("user", "example-user-key")
              .SetPrivate("email", "sandy@example.com")
              .Build();
    ```

    ```c title="C SDK v2.x (native)" theme={null}
            LDUserAddPrivateAttribute(user, "email");
    ```
  </CodeGroup>

  To learn more, read [`ContextBuilder`](https://launchdarkly.github.io/cpp-sdks/libs/server-sdk/docs/html/classlaunchdarkly_1_1ContextBuilder.html).
</Accordion>

### Erlang

<Accordion title="Expand Erlang code sample">
  Here's how to set context attributes as private for all or just some contexts:

  <CodeGroup>
    ```erlang title="Erlang" theme={null}
          %% All attributes marked as private
          ldclient:start_instance("YOUR_SDK_KEY", #{private_attributes => all}).

          %% Two attributes marked as private
          ldclient:start_instance("YOUR_SDK_KEY", #{private_attributes => [<<"email">>, <<"address">>]}).
    ```
  </CodeGroup>

  Here's how to set context attributes as private for a specific context:

  <CodeGroup>
    ```erlang title="Erlang" theme={null}
              ContextWithPrivateAttributes = ldclient_context:set_private_attributes([<<"name">>, <<"/address/street">>],
                  ldclient_context:set(<<"name">>, <<"Global Health Services">>,
                  ldclient_context:set(<<"email">>, <<"info@globalhealthexample.com">>,
                  ldclient_context:set(<<"address">>, #{
                      <<"street">> => <<"123 Main Street">>,
                      <<"city">> => <<"Springfield">>
                  },
              ldclient_context:new(<<"context-key-456def">>, <<"organization">>))))),
    ```
  </CodeGroup>

  In the example, only the `name` and `/address/street` attributes are private for this context.
</Accordion>

### Go

<Accordion title="Expand Go code sample">
  In the Go SDK there are two ways to define private attributes for the entire LaunchDarkly client:

  * You can set the configuration option `AllAttributesPrivate` to true. If you enable this, the SDK removes all attributes for all contexts before it sends the context to LaunchDarkly, except the key and kind.
  * You can set the configuration option `PrivateAttributes` to a list of attribute names. If any context has an attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.

  Here's how to to define private attributes:

  <CodeGroup>
    ```go title="Go SDK v6.0" theme={null}
          import (
              ld "github.com/launchdarkly/go-server-sdk/v6"
              "github.com/launchdarkly/go-server-sdk/v6/ldcomponents"
          )

          var config ld.Config

          // Make all attributes private for all contexts
          config.Events = ldcomponents.SendEvents().AllAttributesPrivate(true)

          // Or, make just the email and address attributes private for all contexts
          config.Events = ldcomponents.SendEvents().
              PrivateAttributes("name", "email")
    ```
  </CodeGroup>

  You can also define a set of private attributes on the context object itself. In the following example, "email" and the "street" field of the "address" attribute are private for this context, in addition to any private attributes that were specified globally:

  <CodeGroup>
    ```go title="Go SDK v6.0" theme={null}
          import (
              "github.com/launchdarkly/go-sdk-common/v3/ldcontext"
          )

          context := ldcontext.NewBuilder("example-context-key").
              Kind("organization").
              Name("Global Health Services").
              SetString("email", "info@globalhealthexample.com").
              SetValue("address", ldvalue.ObjectBuild().
                  SetString("street", "123 Main Street").
                  SetString("city", "Springfield")).
              Private("email").
              Private("/address/street").
              Build()
    ```
  </CodeGroup>
</Accordion>

### Haskell

<Accordion title="Expand Haskell code sample">
  Optionally, you can configure the Haskell SDK to treat some or all context attributes as [private attributes](/home/flags/private-context-attributes). You can use private context attributes for targeting purposes, but the SDK removes private context attributes from the data it sends to LaunchDarkly.

  There are two ways to define private attributes for the entire LaunchDarkly client:

  * When you create the `Config` object, use `configSetAllAttributesPrivate` to set all context attributes as private. When you do this, all context attributes, except the key and kind, are removed before the SDK sends the context to LaunchDarkly.
  * When you create the `Config` object, you can list specific private attributes with `configSetPrivateAttributeNames`. If any context has attributes named in this list, the SDK removes them before sending the context to LaunchDarkly.

  Here's how:

  <CodeGroup>
    ```haskell title="Haskell SDK v4.0" theme={null}
          -- All attributes marked private
          makeConfig "YOUR_SDK_KEY" & configSetAllAttributesPrivate True

          -- Two attributes marked private
          import qualified Data.Set as S
          import qualified LaunchDarkly.Server.Reference as R

          makeConfig sdkKey
            & configSetAllAttributesPrivate True
            & configSetPrivateAttributeNames (S.fromList $ map R.makeLiteral ["name", "email"])
          config = LaunchDarkly::Config.new({private_attributes: ["name", "email"]})
    ```
  </CodeGroup>

  You can also define private attribute names on a per-context basis.

  For example:

  <CodeGroup>
    ```haskell title="Haskell SDK v4.0" theme={null}
          makeContext "key" "user"
            & withName "Sandy"
            & withAttribute "email" "sandy@example.com"
            & withPrivateAttributes (S.fromList $ map R.makeLiteral ["name", "email"])
    ```

    ```haskell title="Haskell SDK v3.x" theme={null}
          import Data.Set (fromList)

          user' = userSetPrivateAttributeNames (fromList ["name", "email"]) user
    ```
  </CodeGroup>
</Accordion>

### Java

<Accordion title="Expand Java code sample">
  In the Java SDK there are two ways to define private attributes for the entire LaunchDarkly client:

  * When creating the `LDConfig` object, you can call the [`allAttributesPrivate`](https://launchdarkly.github.io/java-core/lib/sdk/server/com/launchdarkly/sdk/server/integrations/EventProcessorBuilder.html#allAttributesPrivate-boolean-) method, which takes in a boolean parameter. If `true`, all context attributes except the key for all contexts are removed before the SDK sends the context to LaunchDarkly.
  * When creating the `LDConfig` object, you can call the [`privateAttributes`](https://launchdarkly.github.io/java-core/lib/sdk/server/com/launchdarkly/sdk/server/integrations/EventProcessorBuilder.html#privateAttributes-java.lang.String...-) method, which takes in a set of custom or built-in attributes as a parameter. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.

  Here's how to define private attributes:

  <CodeGroup>
    ```java title="Java SDK v6.0" theme={null}
          // All attributes marked private
          LDConfig configWithAllAttributesPrivate = new LDConfig.Builder()
            .events(
              Components.sendEvents()
                .allAttributesPrivate(true)
            )
            .build();

          // Some attributes marked private
          LDConfig configWithSpecificAttributesPrivate = new LDConfig.Builder()
            .events(
              Components.sendEvents()
                .privateAttributes("name", "email", "someAttribute")
            )
            .build();
    ```
  </CodeGroup>

  You can also mark attributes as private when building the context object by calling the `privateAttributes` builder method. For example:

  <CodeGroup>
    ```java title="Java SDK v6.0" theme={null}
          LDContext context = LDContext.builder("example-context-key")
            .set("email", "sandy@example.com")
            .privateAttributes("email")
            .build();
    ```
  </CodeGroup>

  When the SDK sends this context back to LaunchDarkly, it removes the `email` attribute.
</Accordion>

### Lua

<Accordion title="Expand Lua code sample">
  In the Lua SDK there are two ways to define private attributes for the LaunchDarkly client:

  * Use `allAttributesPrivate` to remove all context attributes except for the kind and key from all contexts before the SDK sends the contexts to LaunchDarkly.
  * Use `privateAttributes` to designate a list of private attributes. If any context has an attribute named in this list, the SDK removes that attribute before sending the context to LaunchDarkly.

  Here's how to mark attributes as private:

  <CodeGroup>
    ```lua title="Lua SDK v2" theme={null}
          -- sets all attributes private
          local configAllPrivate = {
              events = {
                  allAttributesPrivate = true
              }
          }

          -- sets "email" and "address" private
          local configSomePrivate = {
              events = {
                  privateAttributes = { "email", "address" }
              }
          }
    ```

    ```lua title="Lua SDK v1.x" theme={null}
          -- sets all attributes private
          local configAllPrivate = {
              allAttributesPrivate = true
          }

          -- sets "email" and "address" private
          local configSomePrivate = {
              privateAttributeNames = { "email", "address" }
          }
    ```
  </CodeGroup>

  You can also define private attributes for a particular context using a list of `privateAttributes`:

  <CodeGroup>
    ```lua title="Lua SDK v2" theme={null}
          local user = ld.makeContext({
              user = {
                  key  = "example-user-key",
                  attributes = {
                      firstName = "Sandy",
                      lastName  = "Smith",
                      email     = "sandy@example.com",
                      groups    = { "Acme", "Global Health Services" }
                  },
                  privateAttributes = { "email "}
              }
          })
    ```

    ```lua title="Lua SDK v1.x" theme={null}
          local user = ld.makeUser({
              key       = "example-user-key",
              firstName = "Sandy",
              lastName  = "Smith",
              email     = "sandy@example.com",
              custom    = {
                  groups = { "Acme", "Global Health Services" }
              }
              privateAttributeNames = { "email" }
          })
    ```
  </CodeGroup>

  To learn more, read [`clientInit`](https://launchdarkly.github.io/lua-server-sdk/modules/launchdarkly-server-sdk.html#clientInit) and [`makeContext`](https://launchdarkly.github.io/lua-server-sdk/modules/launchdarkly-server-sdk.html#makeContext).
</Accordion>

### Node.js (server-side)

<Accordion title="Expand Node.js (server-side) code sample">
  In the Node.js SDK there are two ways to define private attributes for the entire LaunchDarkly client:

  * In the LaunchDarkly `LDOptions`, you can set `allAttributesPrivate` to `true`. If you enable this, the SDK removes all attributes for all contexts before sending the context to LaunchDarkly, except the kind and key.
  * In the LaunchDarkly `LDOptions` object, you can define a list of `privateAttributes`. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.

  For example:

  <CodeGroup>
    ```js title="Node.js SDK v7.0+ (JavaScript)" theme={null}
          // All attributes marked private
          const options = {
            allAttributesPrivate: true
          };
          client = ld.init('YOUR_SDK_KEY', options);

          // Two attributes marked private
          const options = {
            privateAttributes: ['email', 'address']
          };
          client = ld.init('YOUR_SDK_KEY', options);
    ```

    ```ts title="Node.js SDK v7.0+ (TypeScript)" theme={null}
          // All attributes marked private
          import { LDOptions } from '@launchdarkly/node-server-sdk';
          const options: LDOptions = {
            allAttributesPrivate: true
          };

          const client = ld.init('YOUR_SDK_KEY', options);

          // Two attributes marked private
          import { LDOptions } from '@launchdarkly/node-server-sdk';
          const options: LDOptions = {
            privateAttributes: ['email', 'address']
          };

          const client = ld.init('YOUR_SDK_KEY', options);
    ```
  </CodeGroup>

  You can also define a set of `privateAttributes` on the context object. For example:

  <CodeGroup>
    ```ts title="Node.js SDK v8.x (TypeScript)" theme={null}
          import * as ld from '@launchdarkly/node-server-sdk';

          const user: ld.LDContext = {
            kind: 'user',
            key: 'example-user-key',
            email: 'sandy@example.com',
            privateAttributes: ['email'],
          };
    ```

    ```js title="Node.js SDK v7.x (JavaScript)" theme={null}
          const context = {
            kind: 'user',
            key: 'example-user-key',
            email: 'sandy@example.com',
            _meta: {
              privateAttributes: ['email'],
            }
          };
    ```

    ```ts title="Node.js SDK v7.x (TypeScript)" theme={null}
          import * as ld from 'launchdarkly-node-server-sdk';

          const user: ld.LDContext = {
            kind: 'user',
            key: 'example-user-key',
            email: 'sandy@example.com',
            privateAttributes: ['email'],
          };
    ```
  </CodeGroup>

  When the SDK sends this context back to LaunchDarkly, it removes the `email` attribute.
</Accordion>

### PHP

<Accordion title="Expand PHP code sample">
  In the PHP SDK there are two ways to define private attributes for the entire LaunchDarkly client:

  * In the LaunchDarkly `config`, you can set `all_attributes_private` to `true`. If you enable this, the SDK removes all attributes except the key and kind from a context before sending the context to LaunchDarkly.
  * In the LaunchDarkly `config` object, you can define a list of `private_attribute_names`. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.

  For example:

  <CodeGroup>
    ```php title="PHP SDK v5.0" theme={null}
          // All attributes marked private
          $client = new LaunchDarkly\LDClient($sdkKey, ['all_attributes_private' => true]);

          // Two attributes marked private
          $client = new LaunchDarkly\LDClient($sdkKey, ['private_attribute_names' => ['name', 'email']]);
    ```
  </CodeGroup>

  You can also mark attributes as private when building the context object by calling the equivalent "private" [`LDContextBuilder`](http://launchdarkly.github.io/php-server-sdk/classes/LaunchDarkly-LDContextBuilder.html) method.

  For example:

  <CodeGroup>
    ```php title="PHP SDK v5.0" theme={null}
          $context = LDContext::builder('example-context-key')
              ->set('email', 'sandy@example.com')
              ->private('email')
              ->build();
    ```
  </CodeGroup>

  When the SDK sends this context back to LaunchDarkly, it removes the `email` attribute.
</Accordion>

### Python

<Accordion title="Expand Python code sample">
  In the Python SDK there are two ways to define private attributes for the LaunchDarkly client:

  * In the LaunchDarkly `config`, you can set `all_attributes_private` to true. If you enable this, the SDK removes all context attributes for all contexts before sending the context to LaunchDarkly, except the key.
  * In the LaunchDarkly `config` object, you can define a list of attributes in `private_attributes`. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.

  For example:

  <CodeGroup>
    ```python title="Python SDK v8.0" theme={null}
          # All attributes marked private
          config = Config(all_attributes_private=True)

          # Two attributes marked private
          config = Config(private_attributes=["name", "email"])
    ```
  </CodeGroup>

  You can also mark attributes as private when building the context object by calling the `private` builder method. For example:

  <CodeGroup>
    ```python title="Python SDK v8.0" theme={null}
          context = Context.builder("example-context-key") \
              .set("email", "sandy@example.com") \
              .private("email") \
              .build()
    ```
  </CodeGroup>

  When the SDK sends this context back to LaunchDarkly, it removes the `email` attribute.
</Accordion>

### Ruby

<Accordion title="Expand Ruby code sample">
  In the Ruby SDK there are two ways to define private attributes for the entire LaunchDarkly client:

  * In the LaunchDarkly `config`, you can set `all_attributes_private` to true. If you enable this, the SDK removes all context attributes for all contexts before sending the context to LaunchDarkly, except the key.
  * In the LaunchDarkly config object, you can define a list of `private_attributes`. If any context has a custom or built-in attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.

  For example:

  <CodeGroup>
    ```ruby title="Ruby SDK v7.0" theme={null}
          # All attributes marked private
          config = LaunchDarkly::Config.new({all_attributes_private: true})

          # Two attributes marked private
          config = LaunchDarkly::Config.new({private_attributes: ["name", "email"]})
    ```
  </CodeGroup>

  You can also define a set of `privateAttributes` on the context object. For example:

  <CodeGroup>
    ```ruby title="Ruby SDK v7.0" theme={null}
          context = LaunchDarkly::LDContext.create({
            key: "example-user-key",
            kind: "user",
            firstName: "Sandy",
            lastName: "Smith",
            email: "sandy@example.com",
            groups: ["Acme", "Global Health Services"],
            _meta: {
              privateAttributes: ['email']
            }
          })
    ```
  </CodeGroup>

  When the SDK sends this context back to LaunchDarkly, it removes the `email` attribute.
</Accordion>

### Rust

<Accordion title="Expand Rust code sample">
  In the Rust SDK there are two ways to define private attributes for the entire LaunchDarkly client:

  * In the LaunchDarkly config object, you can set `all_attributes_private` to true. If you enable this, the SDK removes all attributes for all contexts before sending the context to LaunchDarkly, except the key and kind.
  * In the LaunchDarkly config object, you can define a list of `private_attributes`. If any contexts has an attribute named in this list, the SDK removes it before sending the context to LaunchDarkly.

  For example:

  <CodeGroup>
    ```rust title="Rust SDK v1" theme={null}
          // All attributes marked private
          let config_builder = ConfigBuilder::new("YOUR_SDK_KEY");
          let mut processor_builder = EventProcessorBuilder::new();
          processor_builder.all_attributes_private(true);
          config_builder.event_processor(&processor_builder);

          // Two attributes marked private
          let config_builder = ConfigBuilder::new("YOUR_SDK_KEY");
          let mut processor_builder = EventProcessorBuilder::new();
          processor_builder.private_attributes(
              vec!["email".into(), "address".into()]
                  .into_iter()
                  .collect(),
          );
          config_builder.event_processor(&processor_builder);
    ```
  </CodeGroup>

  You can also define private attributes on the context object. For example:

  <CodeGroup>
    ```rust title="Rust SDK v1" theme={null}
          let context = ContextBuilder::new("example-context-key")
              .set_value("email", "youremail@example.com".into())
              .add_private_attribute(Reference::new("email"))
              .build()?;
    ```
  </CodeGroup>

  When the SDK sends this context back to LaunchDarkly, it removes the `email` attribute.
</Accordion>
