> ## 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.

# Context configuration: Server-side SDKs

> This topic explains how to configure contexts in LaunchDarkly SDKs. This feature is available for both client-side and server-side 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 contexts 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, you can construct a [`Context`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Context.html) that only has a key by calling `Context.New`. The context kind defaults to "user," or you can supply a different context kind. Alternatively, you can use the `Context.Builder` method for building a context with other properties.

  The argument to `Builder` is the context's key. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible.

  Here's an example:

  <CodeGroup>
    ```csharp title=".NET SDK v7.0 (C#)" theme={null}
          LDContext context = Context.Builder("example-context-key")
              .Set("firstName", "Sandy")
              .Set("lastName", "Smith")
              .Set("email", "sandy@example.com")
              .Set("groups", LdValue.ArrayOf(LdValue.Of("Acme"), LdValue.Of("Global Health Services")))
              .Build();
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```csharp title=".NET SDK v7.0 (C#)" theme={null}
          var context2 = Context.New(ContextKind.Of("organization"), "example-organization-key");
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```csharp title=".NET SDK v7.0 (C#)" theme={null}
          var userContext = Context.New("example-context-key");

          var deviceContext = Context.Builder("example-device-key")
              .Kind("device")
              .Build();

          var multiContext = Context.NewMulti(userContext, deviceContext);

    ```
  </CodeGroup>

  <Note title="Interpreting custom attribute types">
    The optional name and kind attributes, which you can set with `.Name()` and `.Kind()`, expect string values. If the kind attribute is not specified, it is assumed to be "user." Other attribute values can be booleans, numbers, strings, arrays, or JSON objects. The SDK uses the [`LdValue`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.LdValue.html) type to represent arrays and objects. The .NET SDK is strongly-typed, so be aware of this distinction.
  </Note>

  If an attribute is a JSON object, then in your flag or segment targeting, you can use `/` as a delimiter to refer to specific object fields. For example, if you have an "address" attribute that includes several fields, then you could use `/address/city` in your targeting. To learn more, read [Target with flags](/home/flags/target).

  To learn how to configure private attributes in the .NET (server-side) SDK, read [Private attributes](/sdk/features/private-attributes/server-side#net-server-side).

  To learn how to configure anonymous contexts in the .NET (server-side) SDK, read [Anonymous contexts and users](/sdk/features/anonymous#net-server-side).
</Accordion>

### Apex

<Accordion title="Expand Apex code sample">
  <Warning title="Apex SDK does not support contexts">
    The Apex SDK does not support contexts. Instead, it supports users. You can think of these as contexts with a context kind of "user." Other context kinds are not supported.
  </Warning>

  Here's an example of a user:

  <CodeGroup>
    ```java title="Java" theme={null}
          LDUser user = new LDUser.Builder('example-user-key')
              .setFirstName('Sandy')
              .setLastName('Smith')
              .setEmail('sandy@example.com')
              .setCustom(new LDValueObject.Builder()
                  .set('groups', new LDValueArray.Builder()
                      .add(LDValue.of('Acme'))
                      .add(LDValue.of('Global Health Services'))
                      .build()
                  )
                  .build()
              )
              .build();
    ```
  </CodeGroup>

  The argument to `Builder` is the user's key. The key should uniquely identify each user. You can use a primary key or a hash, as long as the same user always has the same key. We recommend using a hash if possible. In this example, the hash is `"example-user-key"`.

  To learn how to configure private attributes in the Apex SDK, read [Private attributes](/sdk/features/private-attributes/server-side#apex).

  To learn how to configure anonymous users in the Apex SDK, read [Anonymous contexts and users](/sdk/features/anonymous#apex).
</Accordion>

### C++ (server-side)

<Accordion title="Expand C++ (server-side) code sample">
  In the C++ (server-side) SDK, you can construct a context using the `ContextBuilder`. The arguments to `.Kind()` are the context kind and key. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash for the key, as long as the same context always has the same key. We recommend using a hash if possible.

  Here's an example:

  <CodeGroup>
    ```cpp title="C++ SDK v3.0 (native)" theme={null}
          auto context = ContextBuilder()
            .Kind("user", "example-user-key")
            .Set("firstName", "Sandy")
            .Set("lastName", "Smith")
            .Set("groups", {"Acme", "Global Health Services"})
            .Build();
    ```

    ```c title="C++ SDK v3.0 (C binding)" theme={null}
          /* Ensure array_builder.h is included to enable building array values for the context */
          #include <launchdarkly/bindings/c/array_builder.h>

          LDContextBuilder context_builder = LDContextBuilder_New();
          LDContextBuilder_AddKind(context_builder, "user", "example-user-key");
          LDContextBuilder_Attributes_Set(context_builder, "user", "firstName", "Sandy");
          LDContextBuilder_Attributes_Set(context_builder, "user", "lastName", "Smith");

          LDArrayBuilder group_builder = LDArrayBuilder_New();
          LDArrayBuilder_Add(group_builder, LDValue_NewString("Acme"));
          LDArrayBuilder_Add(group_builder, LDValue_NewString("Global Health Services"));

          LDContextBuilder_Attributes_Set(context_builder, "user", "groups", LDArrayBuilder_Build(group_builder));

          LDContext context = LDContextBuilder_Build(context_builder);
    ```

    ```c title="C SDK v2.x (native)" theme={null}
          struct LDUser *user = LDUserNew("example-user-key");
          LDUserSetFirstName(user, "Sandy");
          LDUserSetLastName(user, "Smith");
          LDUserSetEmail(user, "sandy@example.com");

          struct LDJSON *tmp;
          struct LDJSON *custom = LDNewObject();
          struct LDJSON *groups = LDNewArray();
          tmp = LDNewText("Acme");
          LDArrayPush(groups, tmp);
          tmp = LDNewText("Global Health Services");
          LDArrayPush(groups, tmp);
          LDObjectSetKey(custom, "groups", groups);

          LDUserSetCustom(user, custom);
    ```
  </CodeGroup>

  Here's how to construct a context with context kind of something other than "user":

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

    ```c title="C++ SDK v3.0 (C binding)" theme={null}
          LDContextBuilder context_builder = LDContextBuilder_New();
          LDContextBuilder_AddKind(context_builder, "organization", "example-organization-key");

          LDContext context = LDContextBuilder_Build(context_builder);
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```cpp title="C++ SDK v3.0 (native)" theme={null}
          auto context = ContextBuilder()
            .Kind("user", "example-user-key")
            .Name("Sandy")
            .Kind("organization", "example-organization-key")
            .Name("Global Health Services")
            .Build();
    ```

    ```cpp title="C++ SDK v3.0 (C binding)" theme={null}
          LDContextBuilder context_builder = LDContextBuilder_New();
          LDContextBuilder_AddKind(context_builder, "user", "example-user-key");
          LDContextBuilder_Attributes_SetName(context_builder, "user", "Sandy");
          LDContextBuilder_AddKind(context_builder, "organization", "example-organization-key");
          LDContextBuilder_Attributes_SetName(context_builder, "organization", "Global Health Services");
          LDContext context = LDContextBuilder_Build(context_builder);
    ```
  </CodeGroup>

  If you are working in C, when you are done with the context ensure that you free the structure:

  <CodeGroup>
    ```c title="C++ SDK v3.0 (C binding)" theme={null}
          LDContext_Free(context);
    ```

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

  To learn how to configure private attributes in the C++ (server-side) SDK, read [Private attributes](/sdk/features/private-attributes/server-side#c-server-side).

  To learn how to configure anonymous contexts in the C++ (server-side) SDK, read [Anonymous contexts and users](/sdk/features/anonymous#c-server-side).
</Accordion>

### Erlang

<Accordion title="Expand Erlang code sample">
  In the Erlang SDK, use `ldclient_context:set` and `ldclient_context:new` to define and construct a context.

  The `key` property is the context's key. The key is the only mandatory context attribute. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible.

  You can set the kind, or, if you do not set it, LaunchDarkly assumes that the context kind is "user."

  Here's an example of a context:

  <CodeGroup>
    ```erlang title="Erlang SDK v2.0+" theme={null}
              Context = ldclient_context:set(<<"name">>, <<"Sandy Smith">>,
                  ldclient_context:set(<<"email">>, <<"sandy@example.com">>,
                  ldclient_context:set(<<"group">>, [<<"microsoft">>, <<"google">>],
                  ldclient_context:new(<<"example-user-key">>, <<"user">>)))),
    ```

    ```erlang title="Erlang SDK v1.x" theme={null}
          Map = #{
              key => <<"example-user-key">>,
              secondary => <<"secondary-123abc">>,
              ip => <<"198.51.100.0">>,
              country => <<"Canada">>,
              email => <<"sandy@example.com">>,
              first_name => <<"Sandy">>,
              last_name => <<"Smith">>,
              avatar => <<"avatar-123abc">>,
              name => <<"Sandy Smith">>,
              anonymous => false,
              <<"custom-attr-name">> => <<"custom-value">>
          },
          User = ldclient_user:new_from_map(Map)
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```erlang title="Erlang SDK v2.0+" theme={null}
          Context = ldclient_context:new(<<"example-organization-key">>, <<"organization">>)
          %% Or as a map
          Context = #{kind => <<"organization">>, key => <<"example-organization-key">>}
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```erlang title="Erlang SDK v2.0+" theme={null}
          Context = ldclient_context:new_multi_from([
            %% Using `new/1` creates a context with a kind of <<"user">>.
            ldclient_context:new(<<"example-user-key">>),
            %% Using `new/2` creates a context of the specified kind (<<"device">>).
            ldclient_context:new(<<"example-device-key">>, <<"device">>)]). %% kind = device
    ```
  </CodeGroup>

  To learn how to configure private attributes in the Erlang SDK, read [Private attributes](/sdk/features/private-attributes/server-side#erlang).

  To learn how to configure anonymous contexts in the Erlang SDK, read [Anonymous contexts and users](/sdk/features/anonymous#erlang).
</Accordion>

### Go

<Accordion title="Expand Go code sample">
  In the Go SDK, you have two options for how you want to manage contexts:

  * Create a context and pass it in when you initialize an [`LDScopedClient`](https://pkg.go.dev/github.com/launchdarkly/go-server-sdk/v7#LDScopedClient). This is a wrapper around `LDClient` that lets you specify the [evaluation context](/home/flags/contexts#about-contexts) to use for all operations. The scoped client's context is a [multi-context](/home/flags/multi-contexts), and you can update the multi-context with additional associated contexts at any time.
  * Create a context and pass it in to each method call, such as when you [evaluate a flag](/sdk/features/evaluating). To use this option, create a single, shared instance of [`LDClient`](https://pkg.go.dev/github.com/launchdarkly/go-server-sdk/v7#LDClient).

  <Warning title="LDScopedClient is in beta">
    `LDScopedClient` is in beta. It is still undergoing testing and active development. Its functionality may change without notice, including becoming backwards incompatible.
  </Warning>

  The Go SDK defines a `Context` struct and a `Builder`. The context `key` is the only mandatory context attribute. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible.

  Here's an example:

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

          // Context with only a key
          // by default, the context kind is "user"
          context1 := ldcontext.New("example-context-key")

          // Context with a key plus other attributes
          context2 := ldcontext.NewBuilder("context-key-456def").
              Kind("organization").
              Name("Global Health Services").
              SetString("email", "info@globalhealthexample.com").
              SetValue("address", ldvalue.ObjectBuild().
                  SetString("street", "123 Main Street").
                  SetString("city", "Springfield")).
              SetValue("groups", ldvalue.ArrayOf(
                ldvalue.String("Acme"), ldvalue.String("Global Health Services"))).
              Build()
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```go title="Go SDK v6+" theme={null}
          context1 := ldcontext.NewWithKind("organization", "example-organization-key")
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```go title="Go SDK v6+" theme={null}
          multiContext := ldcontext.NewMulti(
              ldcontext.New("example-user-key"),
              ldcontext.NewWithKind("device", "example-device-key")
          )
    ```
  </CodeGroup>

  You can also use the context builder to create each of the individual contexts:

  <CodeGroup>
    ```go title="Go SDK v6+" theme={null}
          multiContext := ldcontext.NewMulti(
              ldcontext.NewBuilder("example-user-key").Name("Sandy").Build(),
              ldcontext.NewBuilder("example-device-key").Kind("device").Name("iPad").Build(),
          )
    ```
  </CodeGroup>

  Each individual context within a multi-context can have the same attributes. The only restriction is that each context has to have a different context `kind` from the others within the multi-context.

  If you're working with `LDScopedClient`, you don't need to manually create the multi-context. Instead, you can add new contexts to the scoped client's multi-context as they become available, or update existing contexts:

  <CodeGroup>
    ```go title="Go SDK v7.13.4+, add contexts to scoped client" theme={null}
          userContext := ldcontext.New("example-user-key")

          scopedClient := ld.NewScopedClient(client, userContext)
          scopedClient.CurrentContext() // returns the single "user" context

          scopedClient.AddContext(ldcontext.NewWithKind("device", "example-device-key"))
          scopedClient.CurrentContext() // returns a multi-context with "user" and "device" contexts

          scopedClient.BoolVariation("example-flag-key", false) // evaluates the flag using a multi-context with "user" and "device" contexts
    ```

    ```go title="Go SDK v7.13.4+, update contexts in scoped client" theme={null}
          userContext := ldcontext.New("example-user-key")

          scopedClient := ld.NewScopedClient(client, userContext)
          scopedClient.CurrentContext() // returns the single "user" context

          scopedClient.AddContext(ldcontext.NewWithKind("device", "example-device-key"))
          scopedClient.CurrentContext() // returns a multi-context with "user" and "device" contexts

          currentUserContext := scopedClient.CurrentContext().IndividualContextByKind("user")
          updatedUserContext := ldcontext.NewBuilderFromContext(currentUserContext)
            .Set("additionalAttribute", "attribute value")
            .Build()
          scopedClient.OverWriteContextByKind(updatedUserContext)

          scopedClient.BoolVariation("example-flag-key", false) // evaluates the flag using a multi-context with updated "user" context and "device" context
    ```
  </CodeGroup>

  After you create a scoped client, we recommend adding it your Go context. Another advantage of using `LDScopedClient` is that you can pass the scoped client to any logic that already takes a Go context (`context.Context`), using utility methods provided in the SDK. This means the scoped client is implicitly passed around through all of your code that uses `context.Context`, and you can access the scoped client anywhere in your application logic. To learn more, read [Use Go contexts with LDScopedClient](/sdk/server-side/go#use-go-contexts-with-ldscopedclient).

  To learn more about the available LaunchDarkly context attributes, read [`Context`](https://pkg.go.dev/github.com/launchdarkly/go-sdk-common/v3@v3.0.0/ldcontext#Context) and [`Builder`](https://pkg.go.dev/github.com/launchdarkly/go-sdk-common/v3@v3.0.0/ldcontext#Builder).

  <Note title="Interpreting attribute types">
    The kind and name attributes expect string values. You can set the kind, or, if you do not set it, LaunchDarkly assumes that the context kind is "user." Other attribute values can be booleans, numbers, strings, arrays, or JSON objects. These types are all represented by the [`ldvalue.Value`](https://pkg.go.dev/github.com/launchdarkly/go-sdk-common/v3@v3.0.0/ldvalue#Value) type. The Go SDK is strongly-typed, so be aware of this distinction.
  </Note>

  If an attribute is a JSON object, then in your flag or segment targeting, you can use `/` as a delimiter to refer to specific object fields. For example, if you have an "address" attribute that includes several fields, then you could use `/address/city` in your targeting. To learn more, read [Target with flags](/home/flags/target).

  To learn how to configure private attributes in the Go SDK, read [Private attributes](/sdk/features/private-attributes/server-side#go).

  To learn how to configure anonymous contexts in the Go SDK, read [Anonymous contexts and users](/sdk/features/anonymous#go).
</Accordion>

### Haskell

<Accordion title="Expand Haskell code sample">
  In the Haskell SDK, use `makeContext` to create a new context. The argument to `makeContext` is the context's key. The key is the only mandatory attribute. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible.

  Here's an example of a context:

  <CodeGroup>
    ```haskell title="Haskell SDK v4.0" theme={null}
          {-# LANGUAGE OverloadedStrings #-}

          import LaunchDarkly.Server.Context

          import Data.Function ((&))

          -- Context with key and kind
          context1 :: Context
          context1 = makeContext "example-context-key" "user"

          -- Context with a key plus other attributes
          context2 :: Context
          context2 = makeContext "context-key-456def" "organization"
              & withAttribute "name" "Global Health Services"
              & withAttribute "email" "info@globalhealthexample.com"
              & withAttribute "address" $ Object $ fromList [("street", "123 Main St"), ("city", "Springfield")]
    ```

    ```haskell title="Haskell SDK v3.x" theme={null}
          {-# LANGUAGE OverloadedStrings #-}

          import LaunchDarkly.Server.User

          import Data.Function ((&))

          -- User with only a key
          user1 :: User
          user1 = (makeUser "example-user-key")

          user2 :: User
          user2 = (makeUser "user-key-456def")
              & setFirstName "Sandy"
              & setLastName "Smith"
              & setEmail "sandy@example.com"
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```haskell title="Haskell SDK v4.0" theme={null}
          makeContext "example-context-key" "organization"
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```haskell title="Haskell SDK v4.0" theme={null}
          makeMultiContext [ makeContext "example-user-key" "user"
                           , makeContext "example-device-key" "device"
                           ]
    ```
  </CodeGroup>

  To learn how to configure private attributes in the Haskell SDK, read [Private attributes](/sdk/features/private-attributes/server-side#haskell).

  To learn how to configure anonymous contexts in the Haskell SDK, read [Anonymous contexts and users](/sdk/features/anonymous#haskell).
</Accordion>

### Java

<Accordion title="Expand Java code sample">
  In the Java SDK, use a [builder pattern](http://en.wikipedia.org/wiki/Builder_pattern) to construct contexts. The argument to `Builder` is the context's key. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible.

  Here's an example:

  <CodeGroup>
    ```java title="Java SDK v6.0" theme={null}
          LDContext context = LDContext.builder("example-context-key")
            .set("firstName", "Sandy")
            .set("lastName", "Smith")
            .set("email", "sandy@example.com")
            .set("groups",
              LDValue.buildArray().add("Acme").add("Global Health Services").build())
            .build();
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```java title="Java SDK v6.0" theme={null}
          LDContext context1 = LDContext.create(ContextKind.of("organization"), "example-organization-key");
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```java title="Java SDK v6.0" theme={null}
          LDContext multiContext = LDContext.createMulti(
              LDContext.create("example-user-key"),
              LDContext.create(ContextKind.of("device"), "example-device-key")
          );
    ```
  </CodeGroup>

  The documentation for [`ContextBuilder`](https://launchdarkly.github.io/java-core/lib/sdk/server/com/launchdarkly/sdk/ContextBuilder.html) shows you all the attributes that LaunchDarkly supports by default.

  <Note title="Interpreting custom attribute types">
    The optional name and kind attributes expect string values. If the "kind" attribute is not specified, it is assumed to be "user." Other attribute values can be booleans, numbers, strings, arrays, or objects. If you pass a value that looks like a number or a boolean, the SDK interprets it that way. The Java SDK is strongly-typed, so be aware of this distinction.
  </Note>

  If an attribute is a JSON object, then in your flag or segment targeting, you can use `/` as a delimiter to refer to specific object fields. For example, if you have an "address" attribute that includes several fields, then you could use `/address/city` in your targeting. To learn more, read [Target with flags](/home/flags/target).

  To learn how to configure private attributes in the Java SDK, read [Private attributes](/sdk/features/private-attributes/server-side#java).

  To learn how to configure anonymous contexts in the Java SDK, read [Anonymous contexts and users](/sdk/features/anonymous#java).
</Accordion>

### Lua

<Accordion title="Expand Lua code sample">
  In the Lua SDK, use `makeContext` to construct a context of any kind. This requires a context `key`. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible. The context attributes are defined as part of the context `kind`.

  To construct a user context specifically, you can use `makeUser`. Both `makeUser` and `makeContext` require a context key. You can omit the `kind` option if you construct your context with `makeUser`. This method is a convenience to make upgrading from the Lua SDK version 1.x to version 2.0 easier. It is deprecated and may be removed in future versions.

  Here's an example of a context:

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

          -- using makeUser, which is deprecated,
          -- to create an identical context (with unique key)
          local user2 = ld.makeUser({
              key       = "example-user-key-2",
              firstName = "Sandy",
              lastName  = "Smith",
              email     = "sandy@example.com",
              custom    = {
                  groups = { "Acme", "Global Health Services" }
              }
          })

          -- using makeContext to create a different kind of context
          local orgContext = ld.makeContext({
              organization = {
                key = "example-organization-key",
                name = "Global Health Services"
              }
          })
    ```

    ```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" }
              }
          })
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```lua title="Lua SDK v2" theme={null}
          -- using makeContext to create a different kind of context
          local orgContext = ld.makeContext({
              organization = {
                key = "example-organization-key",
                name = "Global Health Services"
              }
          })
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```lua title="Lua SDK v2" theme={null}
          -- using makeContext to create a multi-context
          local context = ld.makeContext({
              user = {
                key = "example-user-key"
              },
              org = {
                key = "example-organization-key"
              }
          })
    ```
  </CodeGroup>

  To learn more, read [`makeUser`](https://launchdarkly.github.io/lua-server-sdk/index.html#makeUser) and [`makeContext`](https://launchdarkly.github.io/lua-server-sdk/index.html#makeContext).

  To learn how to configure private attributes in the Lua SDK, read [Private attributes](/sdk/features/private-attributes/server-side#lua).

  To learn how to configure anonymous contexts in the Lua SDK, read [Anonymous contexts and users](/sdk/features/anonymous#lua).
</Accordion>

### Node.js (server-side)

<Accordion title="Expand Node.js (server-side) code sample">
  In the Node.js (server-side) SDK, contexts are JSON objects. The `key` property is the context key. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible.

  Here's an example:

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

          const context: ld.LDContext = {
            kind: 'user',
            key: 'example-user-key',
            firstName: 'Sandy',
            lastName: 'Smith',
            email: 'sandy@example.com',
            groups: ['Acme', 'Global Health Services'],
          };
    ```

    ```js title="Node.js SDK v7.x and later (JavaScript)" theme={null}
          const context = {
            kind: 'user',
            key: 'example-user-key',
            firstName: 'Sandy',
            lastName: 'Smith',
            email: 'sandy@example.com',
            groups: ['Acme', 'Global Health Services'],
          };
    ```

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

          const context: ld.LDContext = {
            kind: 'user',
            key: 'example-user-key',
            firstName: 'Sandy',
            lastName: 'Smith',
            email: 'sandy@example.com',
            groups: ['Acme', 'Global Health Services'],
          };
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```js title="Node.js SDK v7.x and later (JavaScript)" theme={null}
          const context = {
             kind: 'device',
             key: 'example-device-key'
          }
    ```

    ```js title="Node.js SDK v7.x and later (TypeScript)" theme={null}
          const context: ld.LDContext = {
             kind: 'device',
             key: 'example-device-key'
          }
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```js title="Node.js SDK v7.x and later (JavaScript)" theme={null}
          const context = {
            kind: 'multi',
            user: { key: 'example-user-key' },
            device: { key: 'example-device-key' }
          }
    ```

    ```ts title="Node.js SDK v7.x and later (TypeScript)" theme={null}
          const context: ld.LDContext = {
            kind: 'multi',
            user: { key: 'example-user-key' },
            device: { key: 'example-device-key' }
          }
    ```
  </CodeGroup>

  <Note title="Interpreting custom attribute types">
    The optional `name` and `kind` attributes expect string values. If the `kind` attribute is not specified, it is assumed to be "user." Other attribute values can be booleans, numbers, strings, arrays, or JSON objects.
  </Note>

  If an attribute is a JSON object, then in your flag or segment targeting, you can use `/` as a delimiter to refer to specific object fields. For example, if you have an "address" attribute that includes several fields, then you could use `/address/city` in your targeting. To learn more, read [Target with flags](/home/flags/target).

  To learn how to configure private attributes in the Node.js (server-side) SDK, read [Private attributes](/sdk/features/private-attributes/server-side#nodejs-server-side).

  To learn how to configure anonymous contexts in the Node.js (server-side) SDK, read [Anonymous contexts and users](/sdk/features/anonymous#nodejs-server-side).
</Accordion>

### PHP

<Accordion title="Expand PHP code sample">
  In the PHP SDK, use a [builder pattern](http://en.wikipedia.org/wiki/Builder_pattern) to construct contexts. The first argument to [`LDContextBuilder`](http://launchdarkly.github.io/php-server-sdk/classes/LaunchDarkly-LDContextBuilder.html) is the context's key. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible.

  Here's an example:

  <CodeGroup>
    ```php title="PHP SDK v5.0" theme={null}
          $context = LDContext::builder("example-context-key")
              ->set("firstName", "Sandy")
              ->set("lastName", "Smith")
              ->set("email", "sandy@example.com")
              ->set("groups", ["Acme", "Global Health Services"])
              ->build();
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```php title="PHP SDK v5.0" theme={null}
          $context = LDContext::create("example-context-key", "organization");
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```php title="PHP SDK v5.0" theme={null}
          $deviceContext = LDContext::create("example-device-key", "device");
          $orgContext = LDContext::create("example-organization-key", "org");
          $multiContext = LDContext::createMulti($deviceContext, $orgContext);
    ```
  </CodeGroup>

  <Note title="Interpreting custom attribute types">
    The kind and name attributes expect string values. Other attribute values can be booleans, numbers, strings, or arrays. If you enter a custom value on the **Contexts** list that looks like a number or a boolean, the SDK interprets it that way. The PHP SDK is strongly-typed, so be aware of this distinction.
  </Note>

  To learn how to configure private attributes in the PHP SDK, read [Private attributes](/sdk/features/private-attributes/server-side#php).

  To learn how to configure anonymous contexts in the PHP SDK, read [Anonymous contexts and users](/sdk/features/anonymous#php).
</Accordion>

### Python

<Accordion title="Expand Python code sample">
  In version 8.0 and higher of the Python SDK, the [`Context`](https://launchdarkly-python-sdk.readthedocs.io/en/latest/api-main.html#ldclient.Context) class has a `create` method for creating a context with a context kind of "user" and with only a key. It has a `builder` method for building a context with other properties.

  The argument to `Context.builder` is the context's key. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key or a hash, as long as the same context always has the same key. We recommend using a hash if possible.

  Here's an example:

  <CodeGroup>
    ```python title="Python SDK v8.0" theme={null}
          context = Context.builder("example-context-key") \
              .set("firstName", "Sandy") \
              .set("lastName", "Smith") \
              .set("email", "sandy@example.com") \
              .set("groups", ["Acme", "Global Health Services"]) \
              .build()
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```python title="Python SDK v8.0" theme={null}
          context1 = Context.create("example-organization-key", "organization")
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```python title="Python SDK v8.0" theme={null}
          multi_context = Context.create_multi(
              Context.create("example-user-key"),
              Context.create("example-device-key", "device")
          )
    ```
  </CodeGroup>

  If you have many attributes to set, you can also create a context from a dictionary:

  <CodeGroup>
    ```python title="Python SDK v8.0+" theme={null}
          pre_existing_dict = {
              'key': 'example-context-key',
              'kind': 'user',
              'firstName': 'Sandy',
              'lastName': 'Smith',
              'email': 'sandy@example.com',
              'groups': ['Acme', 'Global Health Services'],
          }

          context = Context.from_dict(pre_existing_dict)
    ```
  </CodeGroup>

  <Note title="Interpreting custom attribute types">
    The optional name and kind attributes expect string values. If the "kind" attribute is not specified, it is assumed to be "user." Other attribute values can be booleans, numbers, strings, arrays, or objects.
  </Note>

  If an attribute is a JSON object, then in your flag or segment targeting, you can use `/` as a delimiter to refer to specific object fields. For example, if you have an "address" attribute that includes several fields, then you could use `/address/city` in your targeting. To learn more, read [Target with flags](/home/flags/target).

  To learn more, read [`from_dict`](https://launchdarkly-python-sdk.readthedocs.io/en/latest/api-main.html#ldclient.Context.from_dict).

  To learn how to configure private attributes in the Python SDK, read [Private attributes](/sdk/features/private-attributes/server-side#python).

  To learn how to configure anonymous contexts in the Python SDK, read [Anonymous contexts and users](/sdk/features/anonymous#python).
</Accordion>

### Ruby

<Accordion title="Expand Ruby code sample">
  In the Ruby SDK, contexts are instances of `LaunchDarkly::LDContext`. Legacy users can continue to be provided as simple hashes.

  The `key` property is the context's key. The combination of key and kind must uniquely identify each context. For the key, you can use a primary key, an email address, or a hash string, as long as the same context always has the same key. We recommend using a hash string if possible.

  Here's an 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"]
          })
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```ruby title="Ruby SDK v7.0" theme={null}
          context = LaunchDarkly::LDContext.with_key("example-context-key", "organization")
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```ruby title="Ruby SDK v7.0" theme={null}
          multi_context = LaunchDarkly::LDContext.create_multi([
              LaunchDarkly::LDContext.with_key("example-user-key"),
              LaunchDarkly::LDContext.with_key("example-device-key", "device"),
          ])
    ```
  </CodeGroup>

  <Warning title="Context attribute keys must be symbols">
    All context attribute keys, for both built-in and custom attributes, must be symbols and not strings.
  </Warning>

  <Note title="Interpreting custom attribute types">
    The optional name and kind attributes expect string values. If the "kind" attribute is not specified, it is assumed to be "user" and the hash is assumed to be in the legacy user format. Other attribute values can be booleans, numbers, strings, arrays, or objects. If you enter a custom value on the **Contexts** list that looks like a number or a boolean, the SDK interprets it that way.
  </Note>

  If an attribute is a JSON object, then in your flag or segment targeting, you can use `/` as a delimiter to refer to specific object fields. For example, if you have an "address" attribute that includes several fields, then you could use `/address/city` in your targeting. To learn more, read [Target with flags](/home/flags/target).

  To learn how to configure private attributes in the Ruby SDK, read [Private attributes](/sdk/features/private-attributes/server-side#ruby).

  To learn how to configure anonymous contexts in the Ruby SDK, read [Anonymous contexts and users](/sdk/features/anonymous#ruby).
</Accordion>

### Rust

<Accordion title="Expand Rust code sample">
  The Rust SDK defines a [`Context`](https://docs.rs/launchdarkly-server-sdk/latest/launchdarkly_server_sdk/struct.Context.html) struct and a [`ContextBuilder`](https://docs.rs/launchdarkly-server-sdk/latest/launchdarkly_server_sdk/struct.ContextBuilder.html).

  The context `key` is the only mandatory context attribute. You can set the kind, or, if you do not set it, LaunchDarkly assumes that the context kind is "user." The combination of key and kind must uniquely identify each context. For the key, you can use a primary key, a hash string, or some other value, as long as the same context always has the same key. We recommend using a hash string if possible.

  Here's an example:

  <CodeGroup>
    ```rust title="Rust SDK v3" theme={null}
          // Context with only a key
          let context = ContextBuilder::new("example-context-key").build()?;

          // Context with a key plus other attributes
          let context = ContextBuilder::new("example-context-key")
              .set_value("first_name", "Sandy".into())
              .set_value("last_name", "Smith".into())
              .set_value("email", "sandy@example.com".into())
              .set_value("groups", vec!["Acme", "Global Health Services"].into())
              .build();
    ```
  </CodeGroup>

  Here's how to construct a context with a context kind of something other than "user":

  <CodeGroup>
    ```rust title="Rust SDK v3" theme={null}
          let context = ContextBuilder::new("example-context-key")
              .kind("organization")
              .build()?;
    ```
  </CodeGroup>

  Here's how to construct a multi-context, which includes multiple context kinds:

  <CodeGroup>
    ```rust title="Rust SDK v3" theme={null}
          let user_context = ContextBuilder::new("example-user-key").build()?;
          client.identify(user_context.clone());

          let device_context = ContextBuilder::new("example-device-key").kind("device").build()?;
          client.identify(device_context.clone());

          let multi_context = MultiContextBuilder::new()
          .add_context(user_context)
          .add_context(device_context)
          .build()?;

          client.identify(multi_context);
    ```
  </CodeGroup>

  To learn more about the available attributes, read [`Context`](https://docs.rs/launchdarkly-server-sdk/latest/launchdarkly_server_sdk/struct.Context.html) and [`ContextBuilder`](https://docs.rs/launchdarkly-server-sdk/latest/launchdarkly_server_sdk/struct.ContextBuilder.html).

  <Note title="Interpreting custom attribute types">
    The optional name and kind attributes, which you can set with `.name()` and `.kind()`, expect string values. Other attribute values can be any JSON type, including booleans, numbers, strings, arrays, or objects. These types are all represented by the [`AttributeValue`](https://docs.rs/launchdarkly-server-sdk/latest/launchdarkly_server_sdk/enum.AttributeValue.html) type. The Rust SDK is strongly-typed, so be aware of this distinction.
  </Note>

  If an attribute is a JSON object, then in your flag or segment targeting, you can use `/` as a delimiter to refer to specific object fields. For example, if you have an "address" attribute that includes several fields, then you could use `/address/city` in your targeting. To learn more, read [Target with flags](/home/flags/target).

  To learn how to configure private attributes in the Rust SDK, read [Private attributes](/sdk/features/private-attributes/server-side#rust).

  To learn how to configure anonymous contexts in the Rust SDK, read [Anonymous contexts and users](/sdk/features/anonymous#rust).
</Accordion>
