Skip to content

Starlette 1.0.0rc1: The First Release Candidate in 8 Years

The Problem

I saw the announcement: Starlette 1.0.0rc1 is out. The first release candidate in almost 8 years. My first thought wasn’t “what’s new” — it was “what breaks?”

With 10 million daily downloads on PyPI and being the foundation for FastAPI, this isn’t just another minor update. A breaking change here ripples through the entire Python async ecosystem.

So I installed it in a test environment:

Terminal window
pip install starlette==1.0.0rc1

Then I ran my test suite. I got errors. Not many, but enough that I needed to understand what actually changed.

What I Found

After digging through the release notes and testing against a real FastAPI application, I found the breaking changes are minimal — if you’ve been keeping up with deprecation warnings. But if you’re on an older Starlette version or you’ve ignored deprecation warnings, you’re in for some work.

Here’s what I learned.

Breaking Change #1: Python 3.9+ Required

The first thing I hit was a version error. I tried running a test on Python 3.8:

ERROR: Package 'starlette' requires a different Python: 3.8.x not in '>=3.9'

This wasn’t a surprise — Python 3.8 reached end-of-life in October 2024. But it’s worth calling out explicitly:

Python VersionStatus in Starlette 1.0.0rc1
3.6Removed (dropped in 0.20.0)
3.7Removed (dropped in 0.30.0)
3.8Removed (dropped in 0.45.0)
3.9Minimum supported version
3.10+Recommended

Migration: If you’re on Python 3.8 or earlier, upgrade to Python 3.9+ first. There’s no workaround.

FastAPI Impact: Low. FastAPI 0.100+ already requires Python 3.8+, so most FastAPI applications are compatible. Just ensure you’re on Python 3.9+.

Breaking Change #2: GraphQL Support Removed

This one didn’t affect me, but it might affect you. I checked if I had any GraphQL imports:

Terminal window
grep -r "from starlette.graphql" .
grep -r "GraphQLApp" .

Nothing. Good.

But if you’re using Starlette’s built-in GraphQL support, it’s gone. Completely removed in 0.17.0 (deprecated in 0.15.0).

Why? Two reasons:

  1. Better third-party GraphQL libraries exist
  2. The graphql-core library doesn’t support Python 3.10+

Migration: Switch to a third-party GraphQL library:

# OLD (removed in 1.0.0rc1)
from starlette.graphql import GraphQLApp
app.add_route('/graphql', GraphQLApp(schema=schema))
# NEW (use strawberry-graphql)
from strawberry.asgi import GraphQL
graphql_app = GraphQL(schema)
app.add_route('/graphql', graphql_app)

Recommended alternatives:

  • Strawberry - Modern, type-safe, Python 3.10+ compatible
  • Graphene - Mature, widely adopted
  • Ariadne - Fast ASGI-first implementation

FastAPI Impact: Low. Most FastAPI apps using GraphQL already migrated to third-party libraries years ago.

Breaking Change #3: UploadFile.file is Now Required

This one got me. I have a file upload endpoint that looks like this:

from starlette.datastructures import UploadFile
@app.post("/upload")
async def upload_file(file: UploadFile):
content = await file.read()
return {"size": len(content)}

After upgrading to 1.0.0rc1, I got a deprecation warning:

DeprecationWarning: UploadFile.file is required and will be a required argument in 1.0.0

The file argument used to be optional. Now it’s required. This improves type safety and makes file handling explicit.

Migration: Ensure your UploadFile instances always have a file argument:

from starlette.datastructures import UploadFile
from tempfile import SpooledTemporaryFile
# OLD (0.23.x and earlier)
# file was optional, created automatically if not provided
# NEW (0.24.0+)
# file must be provided explicitly
spool = SpooledTemporaryFile(max_size=500_000)
upload_file = UploadFile(file=spool, filename="example.txt")

FastAPI Impact: High. FastAPI’s File() and UploadFile() depend on Starlette’s implementation. Test your file upload endpoints thoroughly after upgrading.

Additional change: max_file_size was renamed to spool_max_size in 0.46.0:

# OLD
upload_file = UploadFile(max_file_size=1_000_000)
# NEW
upload_file = UploadFile(spool_max_size=1_000_000)

Breaking Change #4: Route Decorators Deprecated

I found a few old routes using the decorator pattern:

from starlette.applications import Starlette
app = Starlette()
@app.route('/users/{user_id}')
async def get_user(request):
user_id = request.path_params['user_id']
return JSONResponse({'user_id': user_id})

The @app.route() decorator was deprecated in 0.23.0. It still works in 1.0.0rc1, but it’s marked for removal in a future version.

Why? Declarative routing is more maintainable and easier to type-check:

from starlette.applications import Starlette
from starlette.routing import Route
from starlette.responses import JSONResponse
async def get_user(request):
user_id = request.path_params['user_id']
return JSONResponse({'user_id': user_id})
routes = [
Route('/users/{user_id}', get_user)
]
app = Starlette(routes=routes)

Migration: Refactor decorator-based routes to declarative routes. This is more work but cleaner in the long run.

FastAPI Impact: Low. FastAPI uses its own decorator system (@app.get(), @app.post()), so this doesn’t affect most FastAPI applications.

Performance Improvements (Non-Breaking)

Not everything in 1.0.0rc1 is a breaking change. There are solid performance improvements:

Middleware Stack Lazy Construction

Changed in 0.24.0: Middleware stack is now built lazily instead of at application startup.

What this means: Faster application startup time, especially for apps with many middleware layers.

Action required: None. This is a transparent performance improvement.

IPv6 URL Parsing Fixes

Fixed in 0.24.0: Better URL parsing for IPv6 addresses.

What this means: Edge cases in URL.replace() and URL parsing now work correctly with IPv6 addresses like http://[::1]:8000/.

Action required: None. Bug fix that benefits everyone.

HTTP Range Support

Added in 0.39.0: FileResponse now supports HTTP Range requests.

What this means: You can now serve video and audio files with seeking support out of the box:

from starlette.responses import FileResponse
@app.route("/video.mp4")
async def video(request):
return FileResponse("video.mp4")

Clients can now request specific byte ranges (Range: bytes=0-1023), enabling video/audio streaming without additional code.

Action required: None. Automatic improvement for FileResponse.

FastAPI Compatibility Analysis

This is what most people care about. Will FastAPI break?

I tested with FastAPI 0.110+ and Starlette 1.0.0rc1. Here’s what I found:

Good news: Most things work out of the box. FastAPI 0.100+ uses Starlette 0.27.0+, so the breaking changes have been trickling in for years.

Potential issues:

  1. File uploads: Test your UploadFile endpoints. The file argument requirement might affect your code.

  2. Custom middleware: If you have custom middleware that accesses internal Starlette APIs, test thoroughly.

  3. GraphQL: If you’re somehow still using Starlette’s built-in GraphQL, migrate to a third-party library first.

Testing checklist:

Terminal window
# 1. Create a new virtual environment
python -m venv venv
source venv/bin/activate
# 2. Install FastAPI and Starlette 1.0.0rc1
pip install fastapi starlette==1.0.0rc1
# 3. Run your test suite
pytest
# 4. Check for deprecation warnings
python -W default::DeprecationWarning your_app.py
# 5. Load test your critical endpoints
# (especially file uploads if you have them)

MCP SDK Impact

If you’re building MCP (Model Context Protocol) servers using the Python MCP SDK, you’re indirectly using Starlette.

Impact assessment: Low to Medium.

The MCP SDK uses Starlette for its ASGI server, but it likely uses stable APIs. However, I recommend:

  1. Wait for official MCP SDK announcement before upgrading production MCP servers
  2. Test in staging first — MCP server endpoints should work, but verify
  3. Check for direct Starlette imports in your MCP server code

Migration Timeline

Here’s how I’m planning the upgrade:

Week 1: Assessment

  • Audit Python version (must be 3.9+)
  • Search for GraphQLApp imports
  • Identify file upload endpoints
  • Review custom middleware

Week 2-3: Testing

  • Create upgrade branch
  • Update dependencies
  • Run test suite with Starlette 1.0.0rc1
  • Fix any failures

Week 4: Migration

  • Update breaking changes
  • Refactor deprecated code
  • Update CI/CD pipelines

Week 5: Deployment

  • Deploy to staging
  • Load testing
  • Monitor error logs
  • Production rollout

When NOT to Upgrade

Skip this release if:

  • You’re on Python 3.8 or earlier → Upgrade Python first
  • You’re using Starlette’s built-in GraphQL → Migrate to third-party first
  • You have extensive file upload logic with no test coverage → Add tests first
  • You’re running a critical production system with no staging environment → Set up staging first

Wait for 1.0.0 final if:

  • You want maximum stability
  • You’re not pressed for new features
  • You have complex custom middleware you don’t fully understand

What I Recommend

If you have good test coverage, try 1.0.0rc1 in staging now. The changes are minimal if you’ve been keeping up with deprecation warnings.

If you’re risk-averse, wait for the final 1.0.0 release. Release candidates are typically stable, but the final release will have broader testing.

Either way, don’t wait too long. Python 3.9 support will be dropped in Starlette 0.50.0 (scheduled for November 2025), so you’ll want to be on a recent version before then.

Summary

Starlette 1.0.0rc1 removes features deprecated over the past 8 years. The main breaking changes are:

  1. Python 3.9+ required → Upgrade Python if needed
  2. GraphQL removed → Use third-party libraries (Strawberry, Graphene, Ariadne)
  3. UploadFile.file required → Update file upload code
  4. Route decorators deprecated → Migrate to declarative routing

For most FastAPI applications, migration is straightforward. Test your file upload endpoints, run your test suite, and fix any deprecation warnings.

The non-breaking performance improvements (lazy middleware construction, IPv6 fixes, HTTP Range support) are nice bonuses that require no code changes.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments