Back to Blog
Python & Backend

FastAPI 0.115 and Pydantic V2: Migration Lessons from a 50-Endpoint Production API

Sritharan K
January 20, 2026
7 min read

FastAPI 0.115 and Pydantic V2: Migration Lessons from a 50-Endpoint Production API

FastAPI 0.115 fully embraces Pydantic V2, which brings significant performance improvements but also breaking changes that the official migration guide doesn't fully cover. I recently migrated a production API with 50+ endpoints, and the process revealed several gotchas that only show up under real-world conditions.

Why Migrate?

Pydantic V2 is 5-20x faster than V1 for validation and serialization. For a high-throughput API, this translates to measurable latency improvements. Our P99 response times dropped by 30% after migration, purely from faster request/response validation.

But the migration isn't automatic. Pydantic V2 changed how validation works, how models serialize, and how custom validators are defined. If you just upgrade dependencies and run tests, you'll miss subtle bugs that only appear in production.

Breaking Change #1: model_validate vs parse_obj

Pydantic V1 used parse_obj() to create model instances from dictionaries. V2 renames this to model_validate(). The migration tool can fix most cases automatically, but if you have dynamic model creation (like in a generic CRUD framework), you'll need to update it manually:

The bigger issue is that model_validate() is stricter about extra fields. In V1, extra fields were silently ignored by default. In V2, you need to explicitly set model_config to allow them:

We had several endpoints that accepted JSON with extra fields (for forward compatibility with mobile clients). After upgrading, those endpoints started returning 422 validation errors. The fix was to add extra='allow' to the affected models.

Breaking Change #2: Serialization Behavior

Pydantic V2 changed how models serialize to JSON. The old dict() method is replaced by model_dump(), and the behavior is different:

The problem is that exclude_unset now behaves differently with nested models. In V1, it would recursively exclude unset fields in nested models. In V2, you need to explicitly pass mode='json' to get the same behavior:

We discovered this when our API started returning null values for optional nested fields that should have been omitted entirely. The client apps expected those fields to be absent, not null.

Breaking Change #3: Custom Validators

Pydantic V2 completely redesigned the validator system. The old @validator decorator is replaced by @field_validator, and the function signature changed:

The key differences:

  • Validators must be class methods (add @classmethod)
  • The decorator is @field_validator, not @validator
  • Validators run before type coercion by default (use mode='after' to run after)

We had custom validators for phone numbers, postal codes, and currency amounts. All of them needed manual updates because the migration tool couldn't handle the logic changes.

Performance Gains

After fixing the breaking changes, we measured the performance impact. For a typical endpoint that validates a request body with 20 fields and returns a response with 50 fields:

  • Request validation: 40% faster
  • Response serialization: 60% faster
  • Overall P99 latency: 30% reduction

The biggest gains were in endpoints that return large lists of objects. Serializing 1000 objects went from 80ms to 25ms.

Migration Strategy

Here's the approach that worked for us:

  • Run the Pydantic migration tool (bump-pydantic) to auto-fix obvious changes
  • Update all custom validators manually
  • Add model_config with extra='allow' to models that need it
  • Change dict() to model_dump(mode='json') everywhere
  • Run the full test suite and fix validation errors
  • Deploy to staging and run load tests to catch performance regressions
  • Monitor error rates closely after production deployment

The migration took about a week for our 50-endpoint API. Most of that time was spent fixing custom validators and testing edge cases.

Should You Migrate?

If you're on FastAPI 0.100 or later, you can stay on Pydantic V1 for now. But Pydantic V2 is the future, and eventually you'll need to migrate. The performance gains are real, especially for high-throughput APIs.

If you're starting a new project, use Pydantic V2 from the beginning. The API is cleaner, the performance is better, and you won't have to deal with migration later.

For existing projects, plan the migration carefully. Budget time for manual fixes, especially if you have custom validators or complex nested models. And test thoroughly before deploying to production.

Planning a complex Python or FastAPI migration? I specialize in auditing and executing large-scale backend transformations.

Book a Strategy Call
FastAPI 0.115 and Pydantic V2: Migration Lessons from a 50-Endpoint Production API | Sritharan K. | SKengineer