- Merge NEW_FEATURES.md into MISSING_BACKEND_API.md as "Future Feature Proposals" - Remove redundant NEW_FEATURES.md file - Add CLAUDE.md to .gitignore (local development config) - Include pending frontend component updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
27 KiB
Missing Backend API Data
This document outlines data that the frontend expects but is not currently provided by the backend API. These features would enhance the match analysis experience.
Impact Summary
| Field | Severity | Status | Impact |
|---|---|---|---|
| KAST % | Critical | Missing | Players display 0% KAST |
| ADR | Critical | Missing | Statistics incomplete |
| Weapon Kills | High | Missing | Weapon stats show 0 kills |
| Round Winner | High | Missing | No round outcome analysis |
| Win Reason | High | Missing | Can't show how rounds ended |
| Headshot % | Medium | Partial | Sometimes missing |
| Damage Stats | Medium | Not extracted | Data sent but unused |
| Utility Stats | Medium | Missing | Grenade analysis unavailable |
| Per-Round Stats | Medium | Missing | No round-by-round performance |
| Loss Bonus | Low | Missing | Economy analysis incomplete |
1. Critical: KAST Percentage
Endpoint: GET /match/{id} (player stats)
Location in Frontend: src/lib/api/players.ts:49-76
Issue: KAST (Kill/Assist/Survive/Trade) is completely unavailable. Frontend returns placeholder 0.
// Current workaround in players.ts
const totalKast = recentMatches.reduce((sum, _m) => {
// KAST is a percentage, we need to calculate it
// For now, we'll use a placeholder
return sum + 0;
}, 0);
Affected Components:
/player/[id]/+page.svelte- Player profile stats chart/match/[id]/+page.svelte:28-29- Team average KAST- Match scoreboard KAST% column
Expected Format:
{
"players": [
{
"kast": 72.5
}
]
}
Backend Implementation: Calculate per player per match:
KAST% = (Rounds with Kill + Rounds with Assist + Rounds Survived + Rounds Traded) / Total Rounds * 100
2. Critical: Average Damage per Round (ADR)
Endpoint: GET /match/{id} (player stats)
Location in Frontend: src/lib/types/Match.ts:114-115
Issue: ADR not provided. Components use player.adr || 0 fallback.
Affected Components:
/match/[id]/+page.svelte:27, 44, 83- Team and player ADR/match/[id]/damage/+page.svelte- Damage analysis page/player/[id]/+page.svelte:280- Player profile
Expected Format:
{
"players": [
{
"adr": 85.3
}
]
}
Backend Implementation:
ADR = Total Damage to Enemies / Rounds Played
3. High: Weapon Kill Counts
Endpoint: GET /match/{id}/weapons
Location in Frontend: src/lib/api/transformers/weaponsTransformer.ts:85-87
Issue: Backend provides damage/hits but NOT kill counts. All weapons show 0 kills.
// Current workaround
weapon_stats.push({
// Kill data not available - API only provides hit/damage events
kills: 0, // HARDCODED ZERO - should be from backend
damage: stats.damage,
hits: stats.hits
});
Expected Format:
{
"weapons": {
"7": {
"kills": 12,
"damage": 1847,
"hits": 45
}
}
}
Backend Implementation: Correlate player_hurt events with player_death events to determine which weapon dealt the killing blow.
4. High: Round Winner & Win Reason
Endpoint: GET /match/{id}/rounds
Location in Frontend: src/lib/api/transformers/roundsTransformer.ts:71-76
Issue: Backend only returns economy data, not round outcomes.
// Current hardcoded placeholders
rounds.push({
round: roundNum + 1,
winner: 0, // HARDCODED - should be 2 (T) or 3 (CT)
win_reason: '', // HARDCODED - should be enum
players
});
Currently Returns:
{
"0": { "player_id": [bank, equipment, spent] },
"1": { "player_id": [bank, equipment, spent] }
}
Expected Format:
{
"0": {
"winner": 2,
"win_reason": "bomb_exploded",
"players": {
"player_id": [bank, equipment, spent]
}
}
}
Win Reason Values:
| Value | Description |
|---|---|
elimination |
All enemies killed |
bomb_defused |
CT defused the bomb |
bomb_exploded |
Bomb detonated (T win) |
time |
Round timer expired (CT win) |
target_saved |
Hostage rescued (rare) |
Backend Implementation: Extract from RoundEnd game events in demo parser.
5. Medium: Damage Statistics (dmg_enemy, dmg_team)
Endpoint: GET /match/{id} (player stats)
Location in Frontend: src/lib/api/transformers.ts:96
Issue: Backend sends dmg as Record<string, unknown> but fields aren't extracted.
// In transformer - data received but not mapped
dmg?: Record<string, unknown>; // NOT EXTRACTED to dmg_enemy/dmg_team
Type Definition (src/lib/types/Match.ts:134-135):
dmg_enemy?: number; // Damage dealt to enemies
dmg_team?: number; // Damage dealt to team (friendly fire)
Expected Format:
{
"players": [
{
"dmg": {
"enemy": 2847,
"team": 45
}
}
]
}
Fix: Either:
- Backend returns flat
dmg_enemyanddmg_teamfields, OR - Frontend transformer extracts from
dmg.enemyanddmg.team
6. Medium: Utility/Grenade Statistics
Endpoint: GET /match/{id} (player stats)
Location in Frontend: src/lib/types/Match.ts:144-148
Issue: Not provided by backend at all.
Missing Fields:
ud_he?: number; // HE grenade damage dealt
ud_flames?: number; // Molotov/Incendiary damage dealt
ud_flash?: number; // Flash grenades thrown (count)
ud_smoke?: number; // Smoke grenades thrown (count)
ud_decoy?: number; // Decoy grenades thrown (count)
Expected Format:
{
"players": [
{
"ud_he": 156,
"ud_flames": 89,
"ud_flash": 8,
"ud_smoke": 12,
"ud_decoy": 2
}
]
}
Backend Implementation: Count grenade events and sum damage from player_hurt events where weapon is HE/molotov/incendiary.
7. Medium: Per-Round Player Statistics
Endpoint: GET /match/{id}/rounds
Issue: No per-round performance data for players.
Missing Fields per Player per Round:
kills_in_round?: number; // Kills in this specific round
damage_in_round?: number; // Damage dealt this round
assists_in_round?: number; // Assists this round
Expected Format:
{
"1": {
"winner": 2,
"win_reason": "elimination",
"players": {
"76561198012345678": {
"bank": 4000,
"equipment": 3750,
"spent": 2900,
"kills": 2,
"damage": 187,
"assists": 1
}
}
}
}
Backend Implementation: Aggregate player_death and player_hurt events per round, grouped by attacker.
8. Low: Loss Bonus Tracking
Endpoint: GET /match/{id}/rounds
Issue: Not tracked in backend.
Missing Fields per Team per Round:
loss_streak?: number; // Consecutive round losses (0-4)
loss_bonus?: number; // Current loss bonus amount
CS2 Loss Bonus Scale:
| Consecutive Losses | Bonus |
|---|---|
| 0 | $1,400 |
| 1 | $1,900 |
| 2 | $2,400 |
| 3 | $2,900 |
| 4+ | $3,400 |
Backend Implementation: Track RoundEnd events and maintain loss counter per team, resetting on win.
9. Optional Fields (Expected Gaps)
These fields are intentionally optional due to data availability:
| Field | Reason |
|---|---|
replay_url |
Only available for matches < 4 weeks old (Valve retention) |
share_code |
Not all matches have share codes |
tick_rate |
May not be in older demos |
game_mode |
Legacy CS:GO matches don't have this |
avg_ping |
Not always recorded in demos |
Backend Implementation Checklist
Priority 1: Critical
- Add KAST calculation per player per match
- Add ADR calculation per player per match
- Add weapon kill tracking (correlate damage with death events)
- Add round winner from
RoundEndevents - Add win_reason enumeration from
RoundEndevents
Priority 2: High
- Extract
dmg_enemyanddmg_teamin player stats - Add utility grenade statistics (ud_he, ud_flames, ud_flash, ud_smoke, ud_decoy)
- Ensure
hs_percentis always calculated
Priority 3: Medium
- Add per-round player stats (kills, damage, assists per round)
- Add loss bonus tracking per team per round
- Ensure
tick_rateis always provided when available
Frontend Readiness
The frontend already has:
- Type definitions for all fields (
src/lib/types/) - Components ready to display data (using fallbacks currently)
- Transformers prepared to extract nested data
- UI for all features (showing placeholders/zeros)
Once backend provides this data, frontend will automatically display it.
API Response Examples
Ideal Match Response
{
"match_id": "123456",
"players": [
{
"id": "76561198012345678",
"name": "Player1",
"kills": 25,
"deaths": 18,
"assists": 4,
"kast": 72.5,
"adr": 85.3,
"hs_percent": 45.2,
"dmg_enemy": 2847,
"dmg_team": 12,
"ud_he": 156,
"ud_flames": 89,
"ud_flash": 8,
"ud_smoke": 12
}
]
}
Ideal Rounds Response
{
"1": {
"winner": 2,
"win_reason": "bomb_exploded",
"t_loss_streak": 0,
"ct_loss_streak": 1,
"players": {
"76561198012345678": {
"bank": 4000,
"equipment": 3750,
"spent": 2900,
"kills": 2,
"damage": 187
}
}
}
}
Ideal Weapons Response
{
"weapons": {
"7": {
"name": "AK-47",
"kills": 12,
"damage": 1847,
"hits": 45,
"headshots": 8
}
}
}
Future Feature Proposals
The following features require backend changes to implement. They are organized into tiers based on implementation complexity.
Tier 3: API Enhancements (Expose Existing Data)
These features use data that's already stored in the database but not currently exposed through the API.
3.1 Per-Weapon Kill Attribution
Current State:
weapontable stores damage per hit withhit_group,weapon_id, anddmg- Weapon damage is aggregated in player meta endpoint
Missing:
- Kill counts per weapon (correlating damage with deaths)
- Headshot kills vs body shot kills per weapon
Proposed API Change:
// Extend GET /player/:id/meta/:limit response
interface WeaponStats {
weapon_id: number;
weapon_name: string;
kills: number; // NEW: Total kills with this weapon
headshot_kills: number; // NEW: HS kills with this weapon
damage: number; // Existing
shots: number; // Existing
hits: number; // Existing
}
Implementation Notes:
- Requires correlating weapon damage events with kill events
- Could be computed at match import time and stored, or calculated on-demand
3.2 Per-Map Detailed Statistics
Current State:
- All player stats exist per match with
mapfield - No pre-aggregated per-map statistics
Missing:
- K/D ratio per map
- ADR per map
- Headshot % per map
- Win rate per map
Proposed API Change:
// Extend GET /player/:id/meta/:limit response
interface MapStats {
map: string;
matches_played: number;
wins: number;
losses: number;
ties: number;
avg_kills: number;
avg_deaths: number;
avg_adr: number;
headshot_pct: number;
}
Use Case: Players can see which maps they perform best on, helping with map vetoes and practice focus.
3.3 Hit Group Aggregates
Current State:
weapon.hit_groupstores where each shot landed (0=head, 1=chest, 2=stomach, 3=left arm, 4=right arm, 5=left leg, 6=right leg)- Individual hits are stored but not aggregated
Missing:
- Aggregated hit distribution across all matches
- Per-weapon accuracy by body part
Proposed API Change:
// Extend GET /player/:id/meta/:limit response
interface HitGroupStats {
total_hits: number;
head: number; // Count of head hits
chest: number; // Count of chest hits
stomach: number; // Count of stomach hits
arms: number; // Combined left+right arm hits
legs: number; // Combined left+right leg hits
head_pct: number; // Calculated percentage
body_pct: number; // chest + stomach percentage
limb_pct: number; // arms + legs percentage
}
Use Case: Visual body diagram showing where player typically lands shots, identifying spray control issues.
3.4 Round Economy Timeline
Current State:
roundstatstable containsbank,equipment,spentper round- Data exists but not exposed in player endpoint
Missing:
- Economy trends over match history
- Buy pattern analysis (eco/force/full buy distribution)
- Equipment value vs damage dealt correlation
Proposed API Change:
// New endpoint: GET /player/:id/economy
interface EconomyStats {
avg_equipment_value: number;
avg_bank_at_round_start: number;
eco_round_pct: number; // % of rounds with <$2000 equipment
force_buy_pct: number; // % of rounds with $2000-$4000
full_buy_pct: number; // % of rounds with >$4000
value_per_kill: number; // avg damage dealt / avg equipment value
save_rate: number; // % of rounds where player survived with <$2000
}
Use Case: Understanding economic efficiency - are they getting value for their money?
3.5 Opponent History (Head-to-Head)
Current State:
- All match participants are stored
- Can identify when two players were in the same match
Missing:
- Head-to-head records vs specific players
- Performance when playing with/against specific teammates
Proposed API Change:
// New endpoint: GET /player/:id/opponents?limit=10
interface OpponentRecord {
opponent_id: string;
opponent_name: string;
opponent_avatar: string;
matches_played: number;
wins: number;
losses: number;
avg_kills_vs: number; // Avg kills when playing against this opponent
avg_deaths_vs: number; // Avg deaths when playing against this opponent
last_match_date: string;
}
Use Case: "Rival" detection - who do they frequently play against and how do they perform?
3.6 Crosshair History
Current State:
crosshaircode stored per matchcolorenum stored (0=default, 1=green, 2=yellow, 3=blue, 4=cyan)
Missing:
- Not exposed in player meta endpoint
- No history of crosshair changes
Proposed API Change:
// Extend GET /player/:id/meta/:limit response
interface CrosshairInfo {
current_crosshair: string; // Most recent crosshair code
current_color: number; // Most recent color
changes_count: number; // How often they change crosshair
history: Array<{
crosshair: string;
color: number;
first_seen: string;
matches_used: number;
}>;
}
Use Case: Players curious about what crosshair settings others use, track experimentation.
Tier 4: Demo Parser Additions
These features require new data collection from demo files during parsing.
4.1 Kill/Death Event Log
What to Capture:
type KillEvent struct {
MatchID string
RoundNumber int
Tick int
Timestamp float64 // Seconds into round
KillerID string
VictimID string
AssisterID string // nullable
WeaponID int
Headshot bool
Wallbang bool
Smoke bool // Through smoke
NoScope bool
Flashed bool // Victim was flashed
Distance float32 // Distance between players
KillerX float32
KillerY float32
KillerZ float32
VictimX float32
VictimY float32
VictimZ float32
}
Enables:
- Opening kill/death statistics (first blood)
- Trade detection (kill within X seconds of teammate death)
- Kill distance analysis (long range vs close quarters)
- Clutch situation detection
- Kill position heatmaps
Storage Estimate: ~20-30 kills per match × 20 bytes average = ~500 bytes per match
4.2 Round Winner Attribution
What to Capture:
type RoundResult struct {
MatchID string
RoundNumber int
WinnerTeamID int // 2 or 3
WinReason int // 1=bomb, 2=defuse, 3=elimination, 4=time
ClutchPlayerID string // nullable - player who clutched (1vX)
ClutchSize int // 1v1, 1v2, etc.
MVPPlayerID string // Round MVP
}
Enables:
- Clutch win rate (1v1, 1v2, 1v3, etc.)
- Bomb plant/defuse success rates
- Round impact scoring
- MVP frequency
4.3 Position/Heatmap Data
What to Capture:
type PlayerPosition struct {
MatchID string
RoundNumber int
Tick int // Sample every ~32 ticks (0.5 seconds)
PlayerID string
X float32
Y float32
Z float32
ViewAngleX float32 // Where they're looking
ViewAngleY float32
IsAlive bool
}
Enables:
- Kill heatmaps (where do they get kills/die)
- Site preference analysis (A vs B)
- Positioning patterns
- 2D round replay (future)
Storage Estimate: High - ~2000 position samples per player per match. Consider:
- Only sample during key moments (kills, bomb plant, round end)
- Downsample to 1 sample per second
- Store as compressed binary blob
4.4 Trade Detection
What to Capture:
- Already covered by Kill Event Log (4.1)
- Calculate at query time: If player A dies and teammate B kills A's killer within 5 seconds = trade
Derived Stats:
interface TradeStats {
trades_given: number; // Times you avenged a teammate
trades_received: number; // Times a teammate avenged you
trade_success_rate: number; // trades_given / opportunities
trading_partner_id: string; // Who they trade with most often
}
4.5 Utility Timing Analysis
What to Capture:
type UtilityEvent struct {
MatchID string
RoundNumber int
Tick int
PlayerID string
UtilityType int // flash, smoke, he, molotov
ThrowX float32
ThrowY float32
ThrowZ float32
LandX float32 // Where it detonated/landed
LandY float32
LandZ float32
PlayersFlashed []FlashedPlayer // For flashbangs
}
type FlashedPlayer struct {
PlayerID string
Duration float32 // Flash duration in seconds
IsTeammate bool
}
Enables:
- Flash effectiveness (avg flash duration)
- Team flash rate (already have
dmg_teambut duration is more precise) - Smoke lineup success
- Molotov damage tracking
4.6 First Blood Statistics
What to Capture:
- Mark
is_first_bloodflag in Kill Event (4.1) - First kill of each round
Derived Stats:
interface FirstBloodStats {
first_blood_attempts: number; // Rounds where they got first kill OR first death
first_bloods: number; // Times they got first kill
first_deaths: number; // Times they died first
first_blood_rate: number; // first_bloods / first_blood_attempts
opening_duel_win_rate: number; // first_bloods / (first_bloods + first_deaths)
}
4.7 HLTV Rating 2.0
Formula Components:
Rating 2.0 = 0.0073*KAST + 0.3591*KPR - 0.5329*DPR + 0.2372*Impact + 0.0032*ADR + 0.1587
Where:
- KAST = % of rounds with Kill, Assist, Survived, or Traded
- KPR = Kills per round
- DPR = Deaths per round
- Impact = (2.13*KPR + 0.42*Assist per Round - 0.41)
- ADR = Average damage per round
What's Needed:
- KAST requires knowing if player survived or was traded (needs trade detection)
- All other components are calculable from existing data
Proposed Implementation:
- Add
kast_roundscounter to match stats - Calculate Rating 2.0 server-side for consistency
Tier 5: New Systems
These features require significant new infrastructure.
5.1 Player Comparison Tool
Description: Side-by-side comparison of any two players' statistics.
Requirements:
- New UI page:
/compare/:player1/:player2 - API endpoint:
GET /players/compare?ids=player1,player2 - Returns normalized stats for fair comparison
Comparison Metrics:
interface PlayerComparison {
players: [PlayerMeta, PlayerMeta];
stats_comparison: {
metric: string;
player1_value: number;
player2_value: number;
player1_percentile: number; // How they rank globally
player2_percentile: number;
}[];
head_to_head?: {
matches_played: number;
player1_wins: number;
player2_wins: number;
};
common_maps: string[];
common_teammates: PlayerMeta[];
}
5.2 Achievement System
Description: Badges and milestones for player accomplishments.
Schema:
CREATE TABLE achievements (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
description TEXT,
icon VARCHAR(50),
category VARCHAR(50), -- 'kills', 'utility', 'milestones', 'special'
threshold INT,
stat_key VARCHAR(50) -- Which stat to check
);
CREATE TABLE player_achievements (
player_id VARCHAR(20),
achievement_id INT,
unlocked_at TIMESTAMP,
progress INT, -- For progressive achievements
PRIMARY KEY (player_id, achievement_id)
);
Example Achievements:
| Name | Description | Threshold |
|---|---|---|
| Centurion | 100 aces | 100 |
| Headhunter | 1000 headshot kills | 1000 |
| Support Main | 500 flash assists | 500 |
| Clutch Master | 50 1v3+ clutches | 50 |
| Map Scholar | Play 100 matches on each map | 700 total |
| Friendly Fire | Deal 1000 team damage (shame badge) | 1000 |
Implementation:
- Background job checks achievement progress after each match import
- Push notification system for newly unlocked achievements
- Achievement showcase on player profile
5.3 Global Leaderboards
Description: Rankings by various statistics.
Schema:
CREATE TABLE leaderboards (
stat_key VARCHAR(50),
time_period VARCHAR(20), -- 'all_time', 'monthly', 'weekly'
player_id VARCHAR(20),
value DECIMAL(10,2),
rank INT,
updated_at TIMESTAMP,
PRIMARY KEY (stat_key, time_period, player_id)
);
Leaderboard Categories:
- Highest K/D ratio (min 50 matches)
- Most headshot kills
- Highest ADR
- Most flash assists
- Most matches played
- Highest win rate (min 100 matches)
- Most aces
- Longest win streak
Implementation:
- Materialized view or dedicated table refreshed hourly/daily
- Pagination support for full leaderboard browsing
- Filter by region/rank bracket (future)
5.4 Improvement Tips Engine
Description: AI-generated suggestions based on weak stats.
Rules Engine Approach:
interface ImprovementRule {
condition: (stats: PlayerStats) => boolean;
tip: string;
priority: number;
category: 'aim' | 'utility' | 'economy' | 'teamplay' | 'consistency';
}
const rules: ImprovementRule[] = [
{
condition: (s) => s.headshot_pct < 30,
tip: 'Your headshot percentage is below average. Focus on crosshair placement at head level.',
priority: 1,
category: 'aim'
},
{
condition: (s) => s.flash_assists < 1,
tip: "You're not getting many flash assists. Practice pop flashes for your teammates.",
priority: 2,
category: 'utility'
},
{
condition: (s) => s.team_damage_ratio > 3,
tip: 'Your team damage is high. Be more careful with utility and spray control.',
priority: 1,
category: 'teamplay'
}
// ... more rules
];
Alternative - ML Approach:
- Cluster players by playstyle
- Compare to higher-ranked players with similar style
- Identify key stat differences
- Generate personalized recommendations
5.5 Match Replay Integration (2D)
Description: Simple 2D overhead view of rounds.
Requirements:
- Position data from Tier 4.3
- Map radar images (already have some)
- WebGL or Canvas-based renderer
- Playback controls (play/pause/speed)
Data Format:
interface ReplayFrame {
tick: number;
timestamp: number; // Seconds into round
players: {
id: string;
team: number;
x: number;
y: number;
angle: number;
health: number;
alive: boolean;
weapon: string;
}[];
events: {
type: 'kill' | 'plant' | 'defuse' | 'flash' | 'smoke';
tick: number;
data: any;
}[];
}
Compression:
- Delta encoding (only send changes)
- Binary format instead of JSON
- Stream in chunks for long rounds
5.6 Social Features
Description: Follow players, activity feed, sharing.
Schema:
CREATE TABLE follows (
follower_id VARCHAR(20),
following_id VARCHAR(20),
created_at TIMESTAMP,
PRIMARY KEY (follower_id, following_id)
);
CREATE TABLE activity_feed (
id SERIAL PRIMARY KEY,
player_id VARCHAR(20),
event_type VARCHAR(50), -- 'match_completed', 'achievement_unlocked', 'rank_changed'
event_data JSONB,
created_at TIMESTAMP
);
Features:
- Follow/unfollow players
- Activity feed showing followed players' recent matches
- Share profile/match links
- Privacy settings (public/private profiles)
Data Schema Reference
Current Tables Used
| Table | Key Fields | Notes |
|---|---|---|
players |
id, name, avatar, tracked | Core player data |
matches |
matchid, map, date, score* | Match metadata |
matchplayers |
All per-player stats | Already comprehensive |
weapon |
hit_group, weapon_id, dmg | Hit registration |
roundstats |
bank, equipment, spent | Economy data |
spray |
spray (gob-encoded) | Spray patterns |
Existing Fields Available but Not Exposed
| Field | Location | Potential Use |
|---|---|---|
crosshair |
matchplayers | Crosshair display |
color |
matchplayers | Crosshair color |
avg_ping |
matchplayers | Network quality |
hit_group |
weapon | Body part accuracy |
spray |
spray | Spray visualization |
Priority Recommendations
High Priority (High Value, Low Effort)
- 3.1 Per-Weapon Kill Attribution - Players want to know their best weapons
- 3.2 Per-Map Detailed Statistics - Essential for competitive players
- 3.3 Hit Group Aggregates - Visual appeal, easy to understand
Medium Priority (High Value, Medium Effort)
- 4.1 Kill/Death Event Log - Unlocks many derived features
- 4.6 First Blood Statistics - Key competitive metric
- 3.5 Opponent History - Engaging "rivalry" feature
Lower Priority (High Effort or Niche Appeal)
- 5.3 Global Leaderboards - Community engagement
- 5.1 Player Comparison - Nice-to-have
- 5.2 Achievement System - Gamification
- 5.5 Match Replay - High effort, impressive feature
Questions for Discussion
- Storage constraints: Position data (4.3) could be large. What's our storage budget?
- Processing time: Kill event parsing (4.1) adds to import time. Acceptable?
- Caching strategy: Meta stats are cached 30 days. Should new aggregates follow same pattern?
- API versioning: Should we version the API or extend existing endpoints?
- Privacy considerations: Should opponent history require consent?
Document consolidated from separate feature proposals Last updated: December 2024