PHPackages                             antikirra/probability - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. antikirra/probability

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

antikirra/probability
=====================

Lightweight PHP micro-library for probabilistic and deterministic code execution — feature flags, A/B testing, gradual rollouts and sampling.

4.0.0(1mo ago)03.1k↓26.2%1MITPHPPHP ^8.2

Since May 24Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/antikirra/probability)[ Packagist](https://packagist.org/packages/antikirra/probability)[ RSS](/packages/antikirra-probability/feed)WikiDiscussions main Synced 2d ago

READMEChangelogDependencies (2)Versions (6)Used By (1)

Make your code work spontaneously 🙃
===================================

[](#make-your-code-work-spontaneously-)

[![Packagist Dependency Version](https://camo.githubusercontent.com/77a910fa3c69bfd488ae5ae44681f13e1f0cc3af4ee952558e718217eee4ccd7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f616e74696b697272612f70726f626162696c6974792f706870)](https://camo.githubusercontent.com/77a910fa3c69bfd488ae5ae44681f13e1f0cc3af4ee952558e718217eee4ccd7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f616e74696b697272612f70726f626162696c6974792f706870)[![Packagist Version](https://camo.githubusercontent.com/dd71eb069f3e31a354c6bbf47abc8b43ee8e617c3f7bd6a2732fe2c8da9f2c5c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616e74696b697272612f70726f626162696c697479)](https://camo.githubusercontent.com/dd71eb069f3e31a354c6bbf47abc8b43ee8e617c3f7bd6a2732fe2c8da9f2c5c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616e74696b697272612f70726f626162696c697479)

A lightweight PHP library for probabilistic code execution and deterministic feature distribution. Perfect for A/B testing, gradual feature rollouts, performance sampling, and controlled chaos engineering.

Quick Start
-----------

[](#quick-start)

```
use function Antikirra\probability;

// Random execution - 30% chance to log debug info
if (probability(0.3)) {
    error_log("Debug: processing request #{$requestId}");
}

// Deterministic execution - same user always gets same experience
if (probability(0.5, "new_checkout_user_{$userId}")) {
    return renderNewCheckout();
}

// Gradual rollout - increase from 10% to 100% over time
if (probability(0.1, "feature_ai_search_user_{$userId}")) {
    enableAISearch();
}
```

Install
-------

[](#install)

```
composer require antikirra/probability:^4.0
```

Requires **PHP 8.2 or newer**. Zero runtime dependencies.

🚀 Key Features
--------------

[](#-key-features)

- **Zero Dependencies** - Pure PHP implementation
- **Deterministic Distribution** - Consistent results for the same input keys
- **High Performance** - Minimal overhead, suitable for high-traffic applications
- **Simple API** - Just one function with intuitive parameters
- **Battle-tested** - Production-ready with predictable behavior at scale

💡 Use Cases
-----------

[](#-use-cases)

- **Performance Sampling** - Log only a fraction of requests to reduce storage costs while maintaining system visibility. Sample database queries, API calls, or user interactions for performance monitoring without overwhelming your logging infrastructure.
- **A/B Testing** - Run controlled experiments with consistent user experience. Test new features, UI changes, or algorithms on a specific percentage of users while ensuring each user always sees the same variant throughout their session.
- **Feature Flags** - Gradually roll out new features with fine-grained control. Start with a small percentage of users and increase over time, or enable features for specific user segments based on subscription tiers or other criteria.
- **Chaos Engineering** - Test system resilience by introducing controlled failures. Simulate random delays, service outages, or cache misses to ensure your application handles edge cases gracefully in production.
- **Rate Limiting** - Implement soft rate limits without additional infrastructure. Control access to expensive operations or API endpoints based on user tiers, preventing abuse while maintaining a smooth experience for legitimate users.
- **Load Balancing** - Distribute traffic across different backend services or database replicas probabilistically, achieving simple load distribution without complex routing rules.
- **Canary Deployments** - Route a small percentage of traffic to new application versions or infrastructure, monitoring for issues before full rollout.
- **Analytics Sampling** - Reduce analytics data volume and costs by tracking only a representative sample of events while maintaining statistical significance.
- **Content Variation** - Test different content strategies, email templates, or notification messages to optimize engagement metrics.
- **Resource Optimization** - Selectively enable resource-intensive features like real-time updates, advanced search, or AI-powered suggestions based on server load or user priority.

🔬 How It Works
--------------

[](#-how-it-works)

The library uses two strategies for probability calculation:

### 1. Pure Random (No Key)

[](#1-pure-random-no-key)

When called without a key, uses PHP's `mt_rand()` for true randomness:

```
probability(0.25); // 25% chance, different result each time
```

### 2. Deterministic (With Key)

[](#2-deterministic-with-key)

When provided with a key, uses CRC32 hashing for consistent results:

```
probability(0.25, 'unique_key'); // Same result for same key
```

**Technical Details:**

- Uses `crc32()` to hash the key into a 32-bit unsigned integer (0 to 4,294,967,295)
- Normalizes the hash by dividing by the bucket count `2³²` (4,294,967,296) to get an unbiased value in `[0.0, 1.0)`
- Compares the normalized value against the probability threshold
- Same key → same hash → same normalized value → deterministic result

The deterministic approach ensures:

- Same input always produces same output
- Uniform distribution across large datasets
- No need for external storage or coordination
- Fast performance (CRC32 is optimized in PHP)

📖 API Reference
---------------

[](#-api-reference)

```
function probability(float $probability, string $key = ''): bool
```

### Parameters

[](#parameters)

- **`$probability`** *(float)*: A value between 0.0 and 1.0

    - `0.0` = Never returns true (0% chance)
    - `0.5` = Returns true half the time (50% chance)
    - `1.0` = Always returns true (100% chance)
- **`$key`** *(string)*: Optional. When provided (non-empty), ensures deterministic behavior

    - Same key always produces same result
    - Different keys distribute uniformly
    - An empty string (the default) falls back to random behavior

### Returns

[](#returns)

- **`bool`**: `true` if the event should occur, `false` otherwise

### Examples

[](#examples)

```
// 15% random chance
probability(0.15);

// Deterministic 30% for user with id 123
probability(0.30, "user_123");

// Combining feature and user for unique distribution
probability(0.25, "feature_checkout_user_123");
```

🎯 Best Practices
----------------

[](#-best-practices)

### 1. Use Meaningful Keys

[](#1-use-meaningful-keys)

```
// ❌ Bad - too generic
probability(0.5, "test");

// ✅ Good - specific and unique
probability(0.5, "homepage_redesign_user_$userId");
```

### 2. Separate Features

[](#2-separate-features)

```
// ❌ Bad - same users get all features
if (probability(0.2, $userId)) { /* feature A */ }
if (probability(0.2, $userId)) { /* feature B */ }

// ✅ Good - different user groups per feature
if (probability(0.2, "feature_a_$userId")) { /* feature A */ }
if (probability(0.2, "feature_b_$userId")) { /* feature B */ }
```

### 3. Consider Scale

[](#3-consider-scale)

```
// For high-frequency operations, use very small probabilities
if (probability(0.001)) { // 0.1% - suitable for millions of requests
    $metrics->record($data);
}
```

📊 When to Use: Random vs Deterministic
--------------------------------------

[](#-when-to-use-random-vs-deterministic)

ScenarioUse Random (no key)Use Deterministic (with key)**Performance sampling**✅ Sample random requests❌ Would sample same requests**Logging/Debugging**✅ Random sampling❌ Not needed for logs**A/B Testing**❌ Inconsistent UX✅ User sees same variant**Feature Rollout**❌ Unpredictable access✅ Stable feature access**Chaos Engineering**✅ Random failures⚠️ Depends on use case**Load Testing**✅ Random distribution❌ Predictable patterns**Canary Deployment**❌ Unstable routing✅ Consistent routing**User Segmentation**❌ Segments change✅ Stable segments💻 Real-World Examples
---------------------

[](#-real-world-examples)

### Laravel: Feature Flag Middleware

[](#laravel-feature-flag-middleware)

```
namespace App\Http\Middleware;

use Closure;
use function Antikirra\probability;

class FeatureFlag
{
    public function handle($request, Closure $next, $feature, $percentage)
    {
        $userId = $request->user()?->id ?? $request->ip();
        $key = "{$feature}_user_{$userId}";

        if (!probability((float)$percentage, $key)) {
            abort(404); // Feature not enabled for this user
        }

        return $next($request);
    }
}

// Usage in routes:
// Route::get('/beta', ...)->middleware('feature:beta_dashboard,0.1');
```

### Symfony: Performance Monitoring

[](#symfony-performance-monitoring)

```
use function Antikirra\probability;
use Psr\Log\LoggerInterface;

class DatabaseQueryLogger
{
    public function __construct(
        private LoggerInterface $logger,
        private float $samplingRate = 0.01 // 1% of queries
    ) {}

    public function logQuery(string $sql, float $duration): void
    {
        // Random sampling - no need for deterministic behavior
        if (!probability($this->samplingRate)) {
            return;
        }

        $this->logger->info('Query executed', [
            'sql' => $sql,
            'duration' => $duration,
            'sampled' => true
        ]);
    }
}
```

### WordPress: A/B Testing

[](#wordpress-ab-testing)

```
use function Antikirra\probability;

function show_homepage_variant() {
    $user_id = get_current_user_id() ?: $_SERVER['REMOTE_ADDR'];
    $key = "homepage_redesign_user_{$user_id}";

    // 50% of users see new design, consistently
    if (probability(0.5, $key)) {
        get_template_part('homepage', 'new');
    } else {
        get_template_part('homepage', 'classic');
    }
}
```

### API Rate Limiting by Tier

[](#api-rate-limiting-by-tier)

```
use function Antikirra\probability;

class ApiRateLimiter
{
    public function allowRequest(User $user, string $endpoint): bool
    {
        $limits = [
            'free' => 0.1,    // 10% of requests allowed
            'basic' => 0.5,   // 50% of requests allowed
            'premium' => 1.0  // 100% of requests allowed
        ];

        $probability = $limits[$user->tier] ?? 0;
        $key = "api_{$endpoint}_{$user->id}_" . date('YmdH'); // Hourly bucket

        return probability($probability, $key);
    }
}
```

🧪 Testing
---------

[](#-testing)

The library includes a comprehensive Pest test suite covering edge cases, statistical correctness, and deterministic behavior.

```
# Install dev dependencies
composer install

# Run tests
composer test
# or
./vendor/bin/pest

# Run with coverage (requires Xdebug or PCOV)
./vendor/bin/pest --coverage
```

Test coverage includes:

- Edge cases (0.0, 1.0, epsilon boundaries)
- Input validation and error handling
- Deterministic key behavior
- Statistical correctness over large sample sizes
- Hash collision handling
- Type coercion

⚡ Performance
-------------

[](#-performance)

Benchmarks on PHP 8.4 (Apple M4 Pro):

OperationTime per callOps/secRandom (no key)~0.12 μs~8.4MDeterministic (with key)~0.15 μs~6.7M**Memory usage:** 0 bytes (no allocations)

The library is optimized for high-throughput scenarios:

- Fast-path optimization for edge cases (0.0, 1.0)
- Minimal function calls
- No object instantiation
- CRC32 is faster than other hash functions

Run `php benchmark.php` to test performance on your hardware.

❓ FAQ / Troubleshooting
-----------------------

[](#-faq--troubleshooting)

### Why do I get different results in different environments?

[](#why-do-i-get-different-results-in-different-environments)

**Q:** Same key returns different results on different servers.

**A:** This is expected! CRC32 implementation is consistent, but you might be using different keys. Ensure you're using the exact same key string across environments.

```
// ❌ This will differ between users
probability(0.5, $userId); // If $userId is different

// ✅ This will be consistent for same user
probability(0.5, "feature_x_user_{$userId}");
```

### Why is my A/B test showing 52% instead of 50%?

[](#why-is-my-ab-test-showing-52-instead-of-50)

**Q:** I'm using `probability(0.5, $userId)` but getting uneven distribution.

**A:** With small sample sizes, variance is normal. The distribution converges to 50% with larger samples (law of large numbers). For 100 users, expect 45-55%. For 10,000 users, expect 49-51%.

### Can I use this for cryptographic purposes?

[](#can-i-use-this-for-cryptographic-purposes)

**Q:** Is this secure for generating random tokens?

**A:** **No!** This library is NOT cryptographically secure. CRC32 is predictable and `mt_rand()` is not suitable for security. Use `random_bytes()` or `random_int()` for security purposes.

### How do I gradually increase rollout percentage?

[](#how-do-i-gradually-increase-rollout-percentage)

**Q:** I want to go from 10% to 50% to 100%.

**A:** Just change the probability value in your code/config. Users in the 0-10% hash range stay enabled, users in 10-50% get added, etc.

```
// Week 1: 10% rollout
if (probability(0.1, "feature_x_user_{$userId}")) { ... }

// Week 2: 50% rollout (includes original 10%)
if (probability(0.5, "feature_x_user_{$userId}")) { ... }

// Week 3: 100% rollout
if (probability(1.0, "feature_x_user_{$userId}")) { ... }
```

### What about hash collisions?

[](#what-about-hash-collisions)

**Q:** Can different keys produce the same result?

**A:** Yes, CRC32 has only 2³² (~4.3 billion) possible values. With many keys, collisions are possible but rare for typical use cases. For most applications this is acceptable. If you need collision-resistant hashing, fork and replace CRC32 with MD5 or SHA256.

### Why not use a database for feature flags?

[](#why-not-use-a-database-for-feature-flags)

**Q:** Isn't a feature flag service better?

**A:** Depends on your needs:

- **Use this library:** Simple rollouts, performance sampling, no persistence needed, minimal dependencies
- **Use feature flag service:** Complex targeting, runtime changes, analytics, team collaboration

This library excels at simplicity and performance, not flexibility.

###  Health Score

48

—

FairBetter than 93% of packages

Maintenance90

Actively maintained with recent releases

Popularity21

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~272 days

Total

5

Last Release

48d ago

Major Versions

1.0.0 → 2.0.02024-02-12

2.1.0 → 3.0.02025-10-18

3.0.0 → 4.0.02026-05-17

PHP version history (2 changes)1.0.0PHP ^5.6 || ^7.0 || ^8.0

4.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/78981782bbc009e5a0fb7b3bde29f28d13e57dff53abf663d319ea87a4308d4c?d=identicon)[antikirra](/maintainers/antikirra)

---

Top Contributors

[![antikirra](https://avatars.githubusercontent.com/u/11780877?v=4)](https://github.com/antikirra "antikirra (19 commits)")

---

Tags

ab-testingexperimentsfeature-flagsfeature-togglesphpprobabilityrandomizationsamplingrandomrolloutprobabilityfeature flagab-testingcanarysamplingchaos-engineering

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/antikirra-probability/health.svg)

```
[![Health](https://phpackages.com/badges/antikirra-probability/health.svg)](https://phpackages.com/packages/antikirra-probability)
```

###  Alternatives

[paragonie/random_compat

PHP 5.x polyfill for random\_bytes() and random\_int() from PHP 7

8.2k686.9M434](/packages/paragonie-random-compat)[markrogoyski/math-php

Math Library for PHP. Features descriptive statistics and regressions; Continuous and discrete probability distributions; Linear algebra with matrices and vectors, Numerical analysis; special mathematical functions; Algebra

2.4k7.6M54](/packages/markrogoyski-math-php)[ircmaxell/random-lib

A Library For Generating Secure Random Numbers

84032.1M132](/packages/ircmaxell-random-lib)[mistic100/randomcolor

Generate attractive random colors

2451.5M6](/packages/mistic100-randomcolor)[pragmarx/random

Create random chars, numbers, strings

744.6M5](/packages/pragmarx-random)[paragonie/random-lib

A Library For Generating Secure Random Numbers

743.6M27](/packages/paragonie-random-lib)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
