DEV Community

Alex
Alex

Posted on

Designing Schemas for Sports APIs: What I Learned Building Football Player Data Systems

Over the past year I’ve been building football-related tools like:

  • player comparison apps
  • squad builders
  • analytics dashboards
  • stat visualizations

And I kept running into the same issue:

Sports data is messy.

Not because the data itself is complicated — but because modeling it cleanly for developers is surprisingly difficult.

At first, I thought this would be simple:
just fetch player data and expose it through an API.

It turned out to be much more of a schema design problem.

The Problem With Flat Structures

My first approach was a completely flat player object:

{
  name: "Ronaldo",
  overall: 99,
  acceleration: 96,
  top_speed: 99,
  finishing: 99,
  shot_power: 99,
  crossing: 94,
  vision: 92
}
Enter fullscreen mode Exit fullscreen mode

This worked initially, but problems appeared quickly:

  • fields became hard to organize
  • frontend components became repetitive
  • adding new stat categories was painful
  • versioned player cards became messy

The biggest issue:

The schema didn’t scale well as the domain became more complex.


Moving to Nested Structures

Instead, I grouped stats semantically:

{
  shooting: {
    score: 99,
    stats: {
      finishing: 99,
      shot_power: 99
    }
  },

  passing: {
    score: 92,
    stats: {
      vision: 92,
      crossing: 94
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This ended up improving several things:

Better Frontend Reusability

UI components became predictable.

Instead of hardcoding fields everywhere, I could dynamically render stat groups.

Easier Versioning

Sports games often have multiple versions of the same player:

  • upgrades
  • special editions
  • seasonal variations

Nested structures made it easier to evolve the schema without constantly rewriting consumers.

Cleaner Mental Model

Grouping related attributes reduced cognitive overhead for both backend and frontend code.


The Real Challenge: Versioned Entities

One thing I underestimated was handling multiple versions of the same player cleanly.

For example:

  • base version
  • upgraded version
  • special event version

Initially I tried patching/updating existing records.

Bad idea.

What worked much better was treating each version as its own immutable entity while keeping shared metadata normalized separately.

That made:

  • caching easier
  • querying simpler
  • historical consistency possible

Performance Considerations

Nested structures are slightly more verbose, but in practice the tradeoff was worth it.

Most consumers preferred:

  • predictable schemas
  • semantic grouping
  • easier frontend rendering

I also heavily optimized read performance through caching since sports data queries are extremely repetitive.


Biggest Lesson

The hardest part of sports APIs usually isn’t collecting the data.

It’s designing a schema that:

  • scales cleanly
  • remains predictable
  • handles versioning well
  • stays frontend-friendly

The better your schema design is early on, the less painful everything becomes later.

Curious how others approach API schema design for highly versioned entities or stat-heavy systems.

Top comments (0)