# Python Core SDK Migration Guide

## Why migrate

* **Performance**: Python Core evaluates faster than the legacy SDK
* **New Features**: Access to Parameter Stores, CMAB (Contextual Multi-Armed Bandits), observabilityClient, and more
* **Future support**: All new features and improvements are available only in Python Core
* **Maintenance**: The legacy Python SDK is in maintenance mode and receives only critical bug fixes

## Installation

{% codetabs %}
```bash Python Core
pip install statsig-python-core
```

```bash Python Legacy
pip install statsig
```
{% /codetabs %}

## StatsigUser

User creation is the same in the new Python Core SDK.

{% codetabs %}
```python Python Core
from statsig_python_core import *

user = StatsigUser(
    user_id="user_123",
    email="user@example.com",
    ip="192.168.0.1",
    user_agent="Mozilla/5.0",
    country="US",
    custom={
        "subscription_level": "premium"
    }
)
```

```python Python Legacy
from statsig import StatsigUser

user = StatsigUser(
    user_id="user_123",
    email="user@example.com",
    ip="192.168.0.1",
    user_agent="Mozilla/5.0",
    country="US",
    custom={
        "subscription_level": "premium"
    }
)
```
{% /codetabs %}

## API changes

### Key package and class changes

| Feature | Python Core SDK | Legacy Python SDK | Status |
|---------|---------------|----------------|--------|
| Package | `statsig_python_core` | `statsig` | ⚠️ Renamed |
| Import | `from statsig_python_core import *` | `from statsig import Statsig` | ⚠️ Change |
| Options | `StatsigOptions` | `StatsigOptions` | ✓ Same |
| User | `StatsigUser` | `StatsigUser` | ✓ Same |
| Initialize | `statsig.initialize().wait()` | `statsig.initialize()` | ⚠️ Added .wait() |
| Check Gate | `statsig.check_gate()` | `statsig.check_gate()` | ✓ Same |
| Get Config | `statsig.get_dynamic_config()` | `statsig.get_config()` | ⚠️ Renamed |
| Get Experiment | `statsig.get_experiment()` | `statsig.get_experiment()` | ✓ Same |
| Get Layer | `statsig.get_layer()` | `statsig.get_layer()` | ✓ Same |
| Log Event | `statsig.log_event()` | `statsig.log_event()` | ✓ Same |
| Shutdown | `statsig.shutdown().wait()` | `statsig.shutdown()` | ⚠️ Added .wait() |

For more details on the new API, go to the [Python Core SDK documentation](https://docs.statsig.com/server-core/python-core).

## Behavioral changes

{% accordion-group %}
{% accordion title="User-Agent Parsing" %}
The SDK now uses a lightweight YAML-based User-Agent parser based on a reduced version of the [ua-parser regex definitions](https://github.com/statsig-io/statsig-server-core/blob/00ad0e4024ca5d30f21892c8f2f23e836165a509/statsig-rust/resources/ua_parser_regex_lite.yaml#L4).

This parser supports the following commonly used browsers:

* Chrome
* Firefox & Firefox Mobile
* Safari & Mobile Safari
* Chrome Mobile
* Android
* Edge & Edge Mobile
* IE Mobile
* Opera Mobile

If your use case requires identifying less common browsers, parse the User-Agent externally before sending it to Statsig.
{% /accordion %}

{% accordion title="Lazy Initialization: User-Agent Parser & Country Lookup" %}
User-Agent parsing and country lookup are now **lazy-loaded by default** to improve SDK initialization performance.

If your application relies on these features being ready **immediately after** `initialize()`, you can opt in by setting:

* `wait_for_user_agent_init`
* `wait_for_country_lookup_init`

⚠️ Enabling these options increases total initialization time.

To **disable** these features entirely, set the `StatsigOptions` flags `disable_user_agent_parsing` and `disable_country_lookup`.
{% /accordion %}

{% accordion title="ID List Feature" %}
The ID List functionality is **disabled by default**.

To enable it, set the `StatsigOptions` flag `enable_id_lists`.
{% /accordion %}

{% accordion title="Endpoint Changes (v1 to v2)" %}
The core SDK now fetches configuration specs from a new endpoint:

* **Old**: `v1/download_config_specs`
* **New**: `v2/download_config_specs`

If you host your own **pass-through proxy**, ensure it supports and correctly routes the `v2` endpoint.

* If you use the **Statsig Forward Proxy (SFP)**, Statsig handles this endpoint migration automatically.
{% /accordion %}

{% accordion title="Environment Evaluation" %}
The server-core SDK evaluates environment in this order: StatsigUser, then StatsigOptions, then defaults to production. The Node SDK uses a different order: StatsigOptions, then StatsigUser, then defaults to production.
{% /accordion %}

{% accordion title="DataStore cache format" %}
**New DataStore cache format**

* **Old**: (Except Node v6+)
  * config_spec cache key is: statsig.cache
  * IDLists statsig.id_lists
* **New**
  * config_spec cache key: `statsig|/v2/download_config_specs|plain_text|{SHA256HashedBase64(secretkey)}`
  * IDLists: Statsig doesn't support idlist data store.
{% /accordion %}
{% /accordion-group %}

## StatsigOptions changes

The table below shows the mapping between legacy SDK options and Server Core SDK options:

| Old Option                                              | New / Notes                                                                                     |
|---------------------------------------------------------|--------------------------------------------------------------------------------------------------|
| `api`                                                   | Deprecated                                                                                       |
| `idlists_thread_limit`, `logging_interval`, `enable_debug_logs`, `events_flushed_callback` | Deprecated                                                                                       |
| `timeout`                                               | Deprecated (was only for network)                                                                |
| `api_for_download_config_specs`                         | `specs_url` – must complete with endpoint                                                        |
| `api_for_get_id_lists`                                  | `id_lists_url` – must complete with endpoint                                                     |
| `api_for_log_event`                                     | `log_event_url` – must complete with endpoint                                                    |
| `tier`                                                  | `environment`                                                                                    |
| `init_timeout`                                          | `init_timeout_ms` – applies to overall initialization (suggest adding +1000 ms if enabling UA)   |
| `rulesets_sync_interval`                                | `specs_sync_interval_ms` (unit: milliseconds)                                                    |
| `idlists_sync_interval`                                 | `id_lists_sync_interval_ms` (unit: milliseconds)                                                 |
| `local_mode`                                            | `disable_network`                                                                                |
| `event_queue_size`                                      | `event_logging_max_queue_size`                                                                  |
| `data_store`                                            | Still supported but interface changed                                                            |
| `fallback_to_statsig_api`                               | Still supported                                                                                  |
| `output_logger_level`                                   | Now `output_log_level`                                                                          |
| `overall_init_timeout`                                  | Replaced by `init_timeout_ms`                                                                   |
| `observability_client`, `sdk_error_callback`            | Now within `observability_client` interface                                                     |
| `custom_logger`                                         | Now `OutputLoggerProvider` interface                                                                             |
| `bootstrap_values`, `evaluation_callback`, `proxy_configs`, `out_of_sync_threshold_in_s`, `rules_updated_callback` | Not yet supported                                                                                |

## Recommended migration path

{% steps %}
{% step title="Add the new Dependencies" %}
* Add the new SDK package/module and any required platform-specific dependencies for your environment.
* Update import or require statements to reference the new SDK namespace or module.
* Keep the old package in place for now. Having both packages running in parallel during local testing can be useful. If needed (depending on the language), you may want to alias the new package.
{% /step %}

{% step title="Update Initialization" %}
* Switch to the new initialization syntax. New SDK keys aren't required. If you update them, ensure they have the same target apps.
* Use the appropriate builder or configuration pattern for setting options. Migrate the StatsigOptions you use, because some were renamed.
{% /step %}

{% step title="Update User Creation" %}
* Migrate to the new format for creating user objects.
* If needed, use the builder pattern or updated constructor to set user properties.
{% /step %}

{% step title="Update Method Calls" %}
* Starting with a few calls, switch your config checks from the old SDK to the new SDK, replacing `oldStatsig.getExperiment()` with `newStatsig.getExperiment()`.
* After changing the package usage, test your service locally or with existing test patterns to build confidence in the new SDK's behavior.
* As you migrate additional calls, update method names that changed (notably, `get_config()` to `get_dynamic_config()`).
* After you're comfortable with the call-by-call migration, consider using refactoring tools to migrate the remaining calls in bulk.
{% /step %}

{% step title="Test Thoroughly" %}
* Verify that all configs are successfully migrated. Run your test suites end-to-end.
{% /step %}

{% step title="Remove old SDK" %}
* Remove references to the old SDK. Clean up old initialization and import logic.
{% /step %}
{% /steps %}

### Additional option: gradual migration using adapter

* Use a migration adapter to wrap the new SDK with the old interface.
* This approach allows incremental migration without updating all call sites at once.
* [Python Core Migration Adapter](https://github.com/statsig-io/statsig-server-core-migration-adapters/blob/main/python_core_migration_adapter.py)

## Need help

If you encounter issues during migration, contact:

* [Statsig Slack Community](https://statsig.com/slack)
* [GitHub Issues](https://github.com/statsig-io/statsig-server-core/issues)
