MATIH Platform is in active MVP development. Documentation reflects current implementation status.
8. Platform Services
Targeting Rules

Targeting Rules

The targeting system provides sophisticated rule-based evaluation for feature flags. The TargetingController at /api/v1/targeting supports multi-dimensional targeting contexts including user attributes, environment details, device information, and custom properties. Rules are evaluated in priority order using a rich set of operators.


TargetingController

@RestController
@RequestMapping("/api/v1/targeting")
@Tag(name = "Feature Flag Targeting", description = "APIs for evaluating feature flags with targeting rules")
public class TargetingController {
    private final TargetingEvaluatorService evaluatorService;
    private final FeatureFlagService flagService;
}

Evaluate Flags with Context

Evaluate one or more feature flags using a full targeting context. The context includes user attributes, environment details, device information, and custom properties.

Endpoint: POST /api/v1/targeting/evaluate

curl -X POST http://localhost:8888/api/v1/targeting/evaluate \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "flagKeys": ["ai.streaming-responses", "bi.new-chart-types"],
    "user": {
      "userId": "user-001",
      "email": "alice@acme.com",
      "username": "alice",
      "groups": ["engineering", "beta-testers"],
      "roles": ["admin", "data-analyst"],
      "plan": "enterprise",
      "isBetaUser": true,
      "isInternal": false,
      "createdAt": "2025-06-15T00:00:00Z"
    },
    "environment": {
      "environment": "production",
      "region": "us-east-1",
      "country": "US"
    },
    "device": {
      "appVersion": "2.5.0",
      "platform": "web",
      "deviceType": "desktop",
      "browser": "chrome",
      "ipAddress": "192.168.1.100",
      "userAgent": "Mozilla/5.0..."
    },
    "custom": {
      "department": "engineering",
      "teamSize": 25,
      "onboardingComplete": true
    },
    "metadata": {
      "requestId": "req-abc-123"
    }
  }'

Response:

{
  "ai.streaming-responses": {
    "flagKey": "ai.streaming-responses",
    "flagId": "880e8400-...",
    "enabled": true,
    "value": "true",
    "variant": null,
    "reason": "TARGETING_MATCH",
    "matchedRule": "beta-users-rule",
    "metadata": { "ruleId": "rule-001", "priority": 1 }
  },
  "bi.new-chart-types": {
    "flagKey": "bi.new-chart-types",
    "flagId": "990e8400-...",
    "enabled": false,
    "value": "false",
    "variant": null,
    "reason": "FLAG_DISABLED",
    "matchedRule": null,
    "metadata": {}
  }
}

Quick Evaluation

A lightweight GET endpoint for simple evaluations with minimal context.

Endpoint: GET /api/v1/targeting/evaluate/{flagKey}

curl "http://localhost:8888/api/v1/targeting/evaluate/ai.streaming-responses?userId=user-001&environment=production" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000"

Targeting Context Structure

The targeting context is organized into four sections:

User Context

AttributeTypeDescription
userIdstringUnique user identifier
emailstringUser email address
usernamestringUsername
groupsstring[]Group memberships
rolesstring[]Assigned roles
planstringSubscription plan (free, pro, enterprise)
isBetaUserbooleanWhether user is a beta tester
isInternalbooleanWhether user is an internal employee
createdAtdatetimeUser creation timestamp

Environment Context

AttributeTypeDescription
environmentstringDeployment environment (dev, staging, production)
regionstringCloud region (us-east-1, eu-west-1)
countrystringCountry code (ISO 3166-1)

Device Context

AttributeTypeDescription
appVersionsemverApplication version
platformstringPlatform (web, ios, android)
deviceTypestringDevice type (mobile, tablet, desktop)
browserstringBrowser name
ipAddressstringClient IP address
userAgentstringUser-Agent header value

Custom Attributes

Any key-value pairs under the custom field. Access them in rules using custom.attributeName.


Available Operators

Endpoint: GET /api/v1/targeting/operators

OperatorDisplay NameDescription
EQUALSEqualsExact string/number match
NOT_EQUALSNot EqualsDoes not match
CONTAINSContainsSubstring match
NOT_CONTAINSNot ContainsDoes not contain substring
STARTS_WITHStarts WithPrefix match
ENDS_WITHEnds WithSuffix match
MATCHES_REGEXMatches RegexRegular expression match
INInValue is one of the provided list
NOT_INNot InValue is not in the list
GREATER_THANGreater ThanNumeric comparison
GREATER_THAN_OR_EQUALGreater Than or EqualNumeric comparison
LESS_THANLess ThanNumeric comparison
LESS_THAN_OR_EQUALLess Than or EqualNumeric comparison
EXISTSExistsAttribute is present
NOT_EXISTSNot ExistsAttribute is absent
IS_TRUEIs TrueBoolean is true
IS_FALSEIs FalseBoolean is false
SEMVER_EQUALSSemver EqualsSemantic version comparison
SEMVER_GREATER_THANSemver Greater ThanSemantic version >
SEMVER_LESS_THANSemver Less ThanSemantic version less-than
BEFOREBeforeDate/time before
AFTERAfterDate/time after

Add a Targeting Rule

Add a targeting rule to a feature flag. Rules are evaluated in priority order (lowest priority number first).

Endpoint: POST /api/v1/targeting/flags/{flagId}/rules

curl -X POST http://localhost:8888/api/v1/targeting/flags/880e8400-e29b-41d4-a716-446655440000/rules \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "name": "Beta Users",
    "description": "Enable for beta testers in the US",
    "priority": 1,
    "enabled": true,
    "conditions": [
      {
        "attribute": "isBetaUser",
        "operator": "IS_TRUE",
        "values": [],
        "caseInsensitive": false,
        "negate": false
      },
      {
        "attribute": "country",
        "operator": "EQUALS",
        "values": ["US"],
        "caseInsensitive": true,
        "negate": false
      }
    ],
    "serveVariant": "true",
    "rolloutPercentage": 100,
    "bucketBy": "userId",
    "metadata": { "team": "growth" }
  }'

Multiple conditions within a single rule are combined with AND logic. All conditions must match for the rule to apply.


Update a Targeting Rule

Endpoint: PUT /api/v1/targeting/flags/{flagId}/rules/{ruleId}

curl -X PUT http://localhost:8888/api/v1/targeting/flags/880e8400-e29b-41d4-a716-446655440000/rules/rule-001 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "name": "Beta Users - All Regions",
    "description": "Enable for beta testers in all regions",
    "priority": 1,
    "enabled": true,
    "conditions": [
      {
        "attribute": "isBetaUser",
        "operator": "IS_TRUE",
        "values": [],
        "caseInsensitive": false,
        "negate": false
      }
    ],
    "serveVariant": "true",
    "rolloutPercentage": 100,
    "bucketBy": "userId"
  }'

Delete a Targeting Rule

Endpoint: DELETE /api/v1/targeting/flags/{flagId}/rules/{ruleId}

curl -X DELETE http://localhost:8888/api/v1/targeting/flags/880e8400-e29b-41d4-a716-446655440000/rules/rule-001 \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000"

Reorder Targeting Rules

Change the evaluation priority of rules by providing the rule IDs in the desired order.

Endpoint: PUT /api/v1/targeting/flags/{flagId}/rules/reorder

curl -X PUT http://localhost:8888/api/v1/targeting/flags/880e8400-e29b-41d4-a716-446655440000/rules/reorder \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -d '["rule-003", "rule-001", "rule-002"]'

Rule Evaluation Flow

For each flag:
  1. Is flag enabled? No -> return DEFAULT
  2. Iterate rules sorted by priority (ascending):
     a. Is rule enabled? No -> skip
     b. Evaluate all conditions (AND logic):
        - Resolve attribute value from context
        - Apply operator against condition values
        - Apply case-insensitive and negate modifiers
     c. All conditions match?
        - Apply rollout percentage (hash(bucketBy) % 100)
        - If within percentage -> return rule's serveVariant
     d. No match -> try next rule
  3. No rule matched -> return DEFAULT

Example: Complex Targeting Rule

Target enterprise users in EMEA running app version 2.0+ on desktop:

{
  "name": "Enterprise EMEA Desktop v2+",
  "priority": 2,
  "enabled": true,
  "conditions": [
    {
      "attribute": "plan",
      "operator": "EQUALS",
      "values": ["enterprise"]
    },
    {
      "attribute": "region",
      "operator": "IN",
      "values": ["eu-west-1", "eu-central-1", "eu-north-1"]
    },
    {
      "attribute": "appVersion",
      "operator": "SEMVER_GREATER_THAN",
      "values": ["2.0.0"]
    },
    {
      "attribute": "deviceType",
      "operator": "EQUALS",
      "values": ["desktop"]
    }
  ],
  "serveVariant": "true",
  "rolloutPercentage": 50,
  "bucketBy": "userId"
}