Implement flat-rate pricing for Code Reviews (0.2 credits per review)

Flat-Rate Pricing for Code Reviews

Overview

Implement flat-rate pricing for Code Reviews where each code review costs a fixed amount (0.2 credits, or 5 reviews = 1 credit) instead of billing per LLM call.

Current Flow (Per-LLM Billing)

Code Review Agent (GitLab)
  ↓
Calls AI Gateway 3 times
  ↓
AI Gateway emits 3 billable events
  ↓
ClickHouse: Multiple events per code review
  ↓
CustomersDot enrichment: Sums all LLM costs
  ↓
Example: 1 code review = 3 LLM calls = 0.6 credits

New Flow (Flat-Rate Billing)

Code Review Agent (GitLab)
  ↓
Completes code review
  ↓
Code Review Agent emits SINGLE billable event
  ↓
ClickHouse: One event per code review
  ↓
CustomersDot enrichment: Fixed cost per event
  ↓
Example: 1 code review = 1 event = 0.2 credits

Key Insight

Flat-rate pricing is NOT a configuration change in CustomersDot. It's a change in where and how billable events are emitted in GitLab.

Aspect Current (Per-LLM) New (Flat-Rate)
Where event emitted AI Gateway (per LLM call) Code Review Agent (per review)
Events per code review Multiple (1 per LLM call) One
Cost calculation Sum of LLM multipliers Fixed 0.2 credits
CustomersDot change None needed Add event type handling
Real work location N/A GitLab (Code Review Agent)

CustomersDot Implementation (Minimal)

Changes Required

Only 2 files need changes:

1. Update app/models/billing/conversion/gitlab_unit_converter.rb

module Billing
  module Conversion
    module GitlabUnitConverter
      def self.calculate_gitlab_credits(event)
        # NEW: Handle flat-rate events with fixed costs
        case event.event_type
        when 'code_review'
          return BigDecimal('0.2')  # 5 code reviews = 1 credit
        when 'pull_request_review'
          return BigDecimal('0.33')  # 3 PR reviews = 1 credit
        end
        
        # Existing: Handle token-based events
        return convert_llm_operations(event) if valid_event?(event)

        raise ::Billing::Conversion::Errors::UnsupportedEventTypeError.new(
          event_type: event.event_type
        )
      end

      private_class_method def self.valid_event?(event)
        event.duo_agent_platform_workflow_completion? ||
          event.code_suggestion_type? ||
          event.ai_gateway_proxy_use_type?
      end

      # ... existing convert_llm_operations and enrich_llm_operations! methods ...
    end
  end
end

2. Add tests to spec/models/billing/conversion/gitlab_unit_converter_spec.rb

context 'when event is code_review' do
  let(:event) do
    build(:usage_event,
      event_type: 'code_review',
      quantity: 1)
  end

  it 'returns flat-rate cost of 0.2 credits' do
    result = described_class.calculate_gitlab_credits(event)

    expect(result).to eq(BigDecimal('0.2'))
  end
end

context 'when event is pull_request_review' do
  let(:event) do
    build(:usage_event,
      event_type: 'pull_request_review',
      quantity: 1)
  end

  it 'returns flat-rate cost of 0.33 credits' do
    result = described_class.calculate_gitlab_credits(event)

    expect(result).to eq(BigDecimal('0.33'))
  end
end

Event Format from GitLab

The Code Review Agent in GitLab should emit events with this structure:

{
  "EventId": "evt-code-review-123",
  "EventType": "code_review",
  "Quantity": 1,
  "UnitOfMeasure": "code_review",
  "Subject": "user-456",
  "RootNamespaceId": 789,
  "Realm": "SaaS",
  "Timestamp": "2025-02-09T10:00:00Z",
  "Metadata": {
    "feature_qualified_name": "code_review/v1"
  }
}

Key Points

  • EventType: Must be code_review (or other flat-rate type)
  • Quantity: Should be 1 (one event per code review)
  • UnitOfMeasure: Can be code_review or similar
  • Metadata: Should include feature_qualified_name for billing eligibility checks

Pricing Examples

Code Reviews (5 reviews = 1 credit)

# Configuration in GitlabUnitConverter
when 'code_review'
  return BigDecimal('0.2')  # 1 / 5 = 0.2

# Event from GitLab
{
  "EventType": "code_review",
  "Quantity": 1
}

# Calculation
1 code review × 0.2 credits = 0.2 credits

Pull Request Reviews (3 reviews = 1 credit)

# Configuration in GitlabUnitConverter
when 'pull_request_review'
  return BigDecimal('0.33')  # 1 / 3 = 0.33

# Event from GitLab
{
  "EventType": "pull_request_review",
  "Quantity": 1
}

# Calculation
1 PR review × 0.33 credits = 0.33 credits

Consumption Flow

Once the event is enriched with the fixed cost, the consumption flow is identical to token-based events:

# 1. Enrichment (calculates credits)
enriched_event = {
  event_id: 'evt-code-review-123',
  event_type: 'code_review',
  gitlab_credits: 0.2,
  quantity: 1
}

# 2. Consumption (deducts from wallets)
Billing::Usage::ConsumptionService.new(
  consumer: consumer,
  gitlab_credits: 0.2,
  user_id: 123,
  event_timestamp: Time.current
).execute

# 3. Wallet transactions recorded
Wallets::Transaction.last
# => {
#   amount: 0.2,
#   metadata: {
#     event_type: 'code_review',
#     ...
#   }
# }

Testing

Manual Testing

# In Rails console

# Test code review event
event = Billing::UsageEvent.new(
  event_id: 'evt-123',
  event_type: 'code_review',
  quantity: 1,
  timestamp: Time.current.to_s
)

credits = Billing::Conversion::GitlabUnitConverter.calculate_gitlab_credits(event)
puts "Credits: #{credits}"  # => 0.2

# Test PR review event
event = Billing::UsageEvent.new(
  event_id: 'evt-456',
  event_type: 'pull_request_review',
  quantity: 1,
  timestamp: Time.current.to_s
)

credits = Billing::Conversion::GitlabUnitConverter.calculate_gitlab_credits(event)
puts "Credits: #{credits}"  # => 0.33

Deployment Checklist

  • Update GitlabUnitConverter with new event types and fixed costs
  • Add unit tests for new event types
  • Add integration tests for enrichment and consumption
  • Create MR with changes
  • Get code review
  • Deploy to staging
  • Verify events are enriched correctly in staging
  • Verify consumption works in staging
  • Deploy to production
  • Monitor consumption and wallet deductions in production
  • Coordinate with GitLab team on Code Review Agent event emission

No Configuration Needed

  • ❌ No pricing_multipliers.yml changes
  • ❌ No new models
  • ❌ No new services
  • ✅ Just add event type handling in GitlabUnitConverter

Summary

Flat-rate pricing in CustomersDot is simple:

  1. Add event type to GitlabUnitConverter
  2. Return fixed cost (e.g., BigDecimal('0.2'))
  3. Add tests

The real work is in GitLab, where the Code Review Agent must:

  • Emit a single billable event per code review (not per LLM call)
  • Include the correct feature_qualified_name in metadata
  • Emit to ClickHouse with the correct event structure

CustomersDot simply recognizes the event type and returns the fixed cost. Everything else (enrichment, consumption, wallet deduction) works automatically.

Related Documentation

  • Usage Billing Development Guide
  • Pricing Multipliers Configuration
  • GitlabUnitConverter
Assignee Loading
Time tracking Loading