Problem
When using statsig-php-core (v0.16.5) with a custom EventLoggingAdapter in a long-running PHP process (Laravel queue worker), the SDK's internal background flush timer fires every ~60 seconds on a Rust tokio thread and attempts to call the PHP adapter's logEvents(). This fails with:
ERROR [Statsig::FunctionBasedEventLoggingAdapterC] Attempted to run FunctionBasedEventLoggingAdapterC on a thread other than the one it was registered on
After 5 retries, events are dropped:
WARN [Statsig::EvtLogger] Scheduled (Max Time) flush failed after 6 attempt(s). 1 Event(s) will be dropped.
Context
- PHP's FFI callbacks are bound to the OS thread that created them (this is a PHP limitation, not a Statsig bug)
- The thread affinity check added in PR #2141 correctly detects this and prevents the crash
- However, there's no way to disable the background flush timer that triggers it
What we've tried
event_logging_flush_interval_ms: 2147483647 — does not work, this parameter is deprecated and ignored in the FFI layer (prefixed with _)
event_logging_max_queue_size: 2147483647 — prevents size-triggered flushes but not time-triggered
disable_all_logging: true — prevents event enqueueing entirely, which we need for exposure logging
Our workaround
We flush events synchronously on the main PHP thread after each checkGate():
$result = $this->statsig->checkGate($user, $gateName);
$this->statsig->flushEvents(); // Runs on main thread, succeeds
return $result;
This works — events are delivered via our custom Redis adapter. The background flush is redundant but can't be disabled, producing noisy error logs every 60 seconds.
We've suppressed the log output with output_log_level: 'none' but the underlying retry/drop cycle still runs.
Environment
statsig/statsig-php-core v0.16.5
- PHP 8.3 (NTS) with FFI enabled
- Long-running Laravel queue workers on AWS ECS (Fargate)
- Custom
EventLoggingAdapter that writes to Redis
Requested fix
Any of these would resolve it:
- Skip background flush when a PHP function-based adapter is in use — since PHP FFI callbacks can never work from a background thread, the timer is always wasted work
- Add a
disable_background_flush option — let the caller take responsibility for flushing
- Honor
event_logging_flush_interval_ms — it's currently deprecated/ignored, but if it worked, setting it to a very large value would be an effective workaround
- Make
ThreadFailure non-retryable — at minimum, don't retry 5 times and log 6 error lines per minute when the failure is guaranteed to repeat
Problem
When using
statsig-php-core(v0.16.5) with a customEventLoggingAdapterin a long-running PHP process (Laravel queue worker), the SDK's internal background flush timer fires every ~60 seconds on a Rust tokio thread and attempts to call the PHP adapter'slogEvents(). This fails with:After 5 retries, events are dropped:
Context
What we've tried
event_logging_flush_interval_ms: 2147483647— does not work, this parameter is deprecated and ignored in the FFI layer (prefixed with_)event_logging_max_queue_size: 2147483647— prevents size-triggered flushes but not time-triggereddisable_all_logging: true— prevents event enqueueing entirely, which we need for exposure loggingOur workaround
We flush events synchronously on the main PHP thread after each
checkGate():This works — events are delivered via our custom Redis adapter. The background flush is redundant but can't be disabled, producing noisy error logs every 60 seconds.
We've suppressed the log output with
output_log_level: 'none'but the underlying retry/drop cycle still runs.Environment
statsig/statsig-php-corev0.16.5EventLoggingAdapterthat writes to RedisRequested fix
Any of these would resolve it:
disable_background_flushoption — let the caller take responsibility for flushingevent_logging_flush_interval_ms— it's currently deprecated/ignored, but if it worked, setting it to a very large value would be an effective workaroundThreadFailurenon-retryable — at minimum, don't retry 5 times and log 6 error lines per minute when the failure is guaranteed to repeat