Skip to content

Commit 26e4631

Browse files
minor cosmetic changes (#506)
* minor cosmetic changes * fixed broken link in ruby docs * minor copy changes
1 parent d458e42 commit 26e4631

File tree

8 files changed

+97
-113
lines changed

8 files changed

+97
-113
lines changed

docs/feature-flagging/index.md

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,11 @@ sidebar_position: 1
55

66
# Eppo Feature Flags
77

8-
Feature flags enable you to easily toggle features on and off, conduct A/B testing, gradually roll out new functionality, and personalize user experiences — all without the need for extensive code deployments.
9-
With feature flags, you can empower your team to make dynamic changes, iterate quickly, and deliver enhanced user experiences with ease.
8+
Feature flags enable you to easily toggle features on and off, conduct A/B/n testing, gradually roll out new functionality, and personalize user experiences — all without the need for extensive code deployments. With feature flags, you can empower your team to make dynamic changes, iterate quickly, and deliver enhanced user experiences with ease.
109

11-
A flag is simply a fork somewhere in your code. Where originally there was a single code path, the presence of a flag creates a gate that splits that path into two or more code paths. In its most basic form a flag object can represented by a human readable name, a key, and a status (on/off). Here's a quick example:
12-
13-
```python
14-
# Before, price is $10 for everyone.
15-
16-
price_of_shoes = 10
17-
```
18-
19-
The presence of a feature flag unlocks multiple paths:
20-
21-
```python
22-
# After, show different prices to different users based on a flag.
23-
24-
group = get_string_assignment('pricing_gate', user_id, user_attributes, 'do_not_round_down')
25-
26-
if (group == "round_down_to_cents"):
27-
price_of_shoes = 9.99
28-
else:
29-
price_of_shoes = 10
30-
```
10+
:::info
11+
This section of the docs covers configuring feature flags and experiments in Eppo's UI. For developer guides on integrating Eppo into your tech stack, please see the [SDKs](/sdks) section.
12+
:::
3113

3214
## Concepts
3315

docs/home.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ The docs are organized into the following sections:
9292
- [**Flag and experiment configuration**](/feature-flagging) - Learn the core concepts, workflows, and use cases for Eppo feature flags and how to configure them in the UI, as well as details on advanced concepts like targeting, mutual exclusion, and global holdouts.
9393
- [**SDKs**](/sdks) - Learn about how to install and use Eppo's SDKs into your environment(s), as well as more details on the Eppo architecture and supported deployment patterns.
9494
- [**Data Management**](/data-management) - Learn about Eppo's data and metric model, how to connect your data warehouse, and how to use Eppo to manage data governance across experimentation use cases.
95-
- [**Experiment Analysis**](/experiment-analysis) - Learn about how to create experiment analysis in Eppo's UI, as well as how to deep dive into experiment results and curate custom experiment reports to communicate and track learnings.
95+
- [**Experiment Analysis**](/experiment-analysis) - Learn how to create experiment analysis in Eppo's UI, as well as how to deep dive into experiment results and curate custom experiment reports to communicate and track learnings.
9696
- [**Contextual Bandits**](/contextual-bandits) - Learn how to use Eppo to personalize user experiences with contextual bandits.
9797

9898
#### Reference

docs/sdks/common-issues.md

Lines changed: 0 additions & 85 deletions
This file was deleted.

docs/sdks/datadog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import TabItem from '@theme/TabItem';
88

99
## Overview
1010
This guide will walk through how to send Eppo feature flag assignments as RUM data to Datadog.
11-
This functionality enhances your ability to monitor user experience and performance by enabling you to identify which users are exposed to a particular feature and assess whether any introduced change impacts the user experience or degrades performance
11+
This functionality enhances your ability to monitor user experience and performance by enabling you to identify which users are exposed to a particular feature and assess whether any introduced change impacts the user experience or degrades performance.
1212

1313
Enhancing your real-user monitoring data with feature flag information allows you to verify that new features are launched smoothly, without inadvertently introducing bugs or performance regressions. This added level of visibility enables you to establish connections between feature releases and performance metrics, rapidly identify issues tied to specific releases, and expedite troubleshooting efforts.
1414

docs/sdks/faqs/common-issues.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
sidebar_position: 10
3+
---
4+
5+
# Best practices
6+
7+
This page walks through some best practices to consider when integrating Eppo’s SDK.
8+
9+
:::note
10+
Don't be blocked! We're here to help you get up and running with Eppo. Contact us at [[email protected]](mailto:[email protected]).
11+
:::
12+
13+
## Assign as close to the split in experience as possible
14+
15+
In general, strive to place assignment calls as close to code split as possible. This reduces the likelihood of logging an assignment but not delivering the corresponding experience, leading to analysis issues such as impact dilution.
16+
17+
Suppose we are testing a new payment experience with users. It’s best to fetch the assignment and deliver the experience as close together in the code as possible:
18+
19+
```javascript
20+
export default function PaymentPage({ user: User }): JSX.Element {
21+
const useNewPaymentFlow =
22+
eppoClient.getBooleanAssignment("new-payment-flow", user.email, {}, false) === true;
23+
24+
return (
25+
<Container>
26+
{useNewPaymentFlow ? (
27+
<PaymentPageV2 user={user} />
28+
) : (
29+
<PaymentPage user={user} />
30+
)}
31+
</Container>
32+
);
33+
}
34+
```
35+
36+
In this example, assignment and delivery are tightly coupled. Users who are assigned the new payment page always see the new one, and users who are assigned the old payment page always see the old one. There is very little chance for an assignment to be logged without the user experiencing the new variant.
37+
38+
:::info
39+
While Eppo recommends placing assignment calls as close to the code split as possible, we understand this is not possible in all circumstances. In these cases, we provide the ability to filter analysis results. See [filtering assignments by entry points](/experiment-analysis/configuration/filter-assignments-by-entry-point) for more details.
40+
:::
41+
42+
43+
## Avoid round trips to internal servers
44+
45+
It may be tempting to implement to centralize experiment assignment on an internal server. This would remove the need to fetch flag configurations from Eppo's network independently for each individual who uses your application. This however either incurs latency each time a flag is evaluated (from doing a round trip to your internal server), or encourages implementing a "fetch all flags at initialization" approach, in direct conflict with the previous best practice.
46+
47+
Eppo's client-side SDKs are designed to mitigate both of these problems. By pre-fetching an obfuscated flag configuration, the full assignment logic can happen locally without any network calls. Further, by only evaluating flag values when the feature is rendered, we guarantee high-quality analytic data.
48+
49+
Accordingly, Eppo recommends using the client-side SDK for most use cases. The main exception is when the experience originates from the backend, e.g. A/B testing machine learning models whose predictions are generated server-side.
50+
51+
Eppo's SDK will by default fetch configurations from our global CDN hosted on Fastly. In most situations, this round trip completes in [under 20ms](/sdks/faqs/latency), but some teams may prefer to remove the dependency all together. In this case, you can fetch Eppo's configuration file independently and then pass that to the client as part of routine app initialization. To read more about that, please see the [deployment modes](/sdks/architecture/deployment-modes#local-flag-evaluation-using-configurations-from-internal-server) page.
52+
53+
54+
## Avoid targeting with a long list of user IDs
55+
56+
Eppo targeting works based on subject attributes passed into the `get<Type>Assignment` function. It is tempting to use these targeting rules to define a list of specific users to target. However, this can lead to performance issues as now every time the SDK is initialized, this full list of users need to be pulled in from the Eppo CDN. To help keep the Eppo SDK lightweight, we limit the list of specific values you can target to 50.
57+
58+
A better pattern is to define audiences via user-level attributes. For instance, if you would like to target a list of beta users, you can pass an attribute into the `get<Type>Assignment` call specifying whether the user is in the beta group.
59+
60+
```javascript
61+
const variation = eppoClient.getStringAssignment("my-flag-key", "userId", {
62+
beta_user: "true",
63+
}, "control");
64+
```
65+
66+
Now, simply add allocation logic specifying to target users with `beta_user = 'true'`:
67+
68+
![Add attribute to allocation](/img/feature-flagging/add-attribute-to-allocation.png)
69+
70+
This does require you to determine whether a user is in the beta group before calling `get<Type>Assignment`, but it helps to keep the Eppo SDK very light.
71+
72+
73+
74+
75+
76+
77+
## Consider how to best handle non-blocking initialization
78+
79+
Most initialization methods in Eppo’s SDKs are non-blocking in order to minimize their footprint on the applications in which they are run. One consequence of this, however, is that it is possible to invoke the `get<Type>Assignment` method before the SDK has finished initializing. If `get<Type>Assignment` is invoked before the SDK has finished initializing, the SDK may not have access to the most recent configurations. There are two possible outcomes when `get<Type>Assignment` is invoked before the SDK has finished initializing:
80+
81+
1. If the SDK downloads configurations to a persistent store, e.g. the JavaScript client SDK uses local storage, and a configuration was previously downloaded, then the SDK will assign a variation based on a previously downloaded configuration.
82+
83+
2. If no configurations were previously downloaded or the SDK stores the configuration in memory and loses it during re-initialization, then the SDK will return the default value when `get<Type>Assignment` is invoked.
84+
85+
Most SDKs have an option to `waitForInitialization`, as well as flexible initialization options that you can pass in at initialization.

docs/sdks/server-sdks/python/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import TabItem from '@theme/TabItem';
55

66
Eppo's Python SDK can be used for both feature flagging and experiment assignment:
77

8-
- [GitHub repository](https://github.com/Eppo-exp/python-sdk)
8+
- [GitHub repository](https://github.com/Eppo-exp/rust-sdk/tree/main/python-sdk)
99
- [PyPI package](https://pypi.org/project/eppo-server-sdk/)
1010

1111
## Getting Started

docs/sdks/server-sdks/ruby.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import TabItem from '@theme/TabItem';
55

66
Eppo's Ruby SDK can be used for both feature flagging and experiment assignment:
77

8-
- [GitHub repository](https://github.com/Eppo-exp/ruby-sdk)
8+
- [GitHub repository](https://github.com/Eppo-exp/rust-sdk/tree/main/ruby-sdk)
99
- [RubyGems gem](https://rubygems.org/gems/eppo-server-sdk/)
1010

1111
## 1. Install the SDK
@@ -39,7 +39,7 @@ If you are using the SDK for experiment assignments, make sure to pass in an ass
3939

4040
:::info
4141

42-
By default the Eppo client initialization is asynchronous to ensure no critical code paths are blocked. For more information on handling non-blocking initialization, see our [documentation here](/sdks/common-issues#3-not-handling-non-blocking-initialization).
42+
By default the Eppo client initialization is asynchronous to ensure no critical code paths are blocked. For more information on handling non-blocking initialization, see our [documentation here](/sdks/faqs/common-issues/#consider-how-to-best-handle-non-blocking-initialization).
4343

4444
:::
4545

static/_redirects

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,6 @@ http://adoring-yonath-6ecb9d.netlify.app/* http://docs.geteppo.com/:splat 301!
126126

127127
/sdks/overview /sdks/architecture/overview
128128

129-
/sdks/architecture /sdks/architecture/overview
129+
/sdks/architecture /sdks/architecture/overview
130+
131+
/sdks/common-issues/ /sdks/faqs/common-issues/

0 commit comments

Comments
 (0)