Python Tornado
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This section is written against Tornado 6.5.10 (released 2026-09-15) on Python 3.13, checked on 2026-10-07. Tornado 6.5
supports Python 3.9 and newer. Tornado 6.6 is not released yet: only the alpha 6.6a1 (2026-09-22) is on PyPI and its
final release notes are still dated "Oct XX, 2026", so everything described as 6.6 in this section (Python 3.11 as the
minimum, the cross_origin_protection and trusted_origins settings, the deprecation of OpenIdMixin) is upcoming
and can still change. Every page notes the version in which a feature appeared, because Tornado changed a lot between
4.x and 6.x and most tutorials on the web still show the older idioms.
What Tornado is
Tornado is a Python web framework and asynchronous networking library that started life at FriendFeed. It bundles four
things that other stacks keep in separate projects: a web framework (tornado.web: Application, RequestHandler,
templates, cookies, XSRF protection, WebSockets), an HTTP server and client (HTTPServer, AsyncHTTPClient), a
non-blocking networking layer (IOLoop and IOStream, now thin wrappers around asyncio), and coroutine tools
(tornado.gen, tornado.queues, tornado.locks).
The defining design choice is that Tornado is not a WSGI framework. It brings its own HTTP server and runs every
request of a process on one thread and one event loop. A handler that waits (for a database, a remote service or a
client) does so with await and lets the loop serve other connections meanwhile. That makes Tornado a good fit for
workloads with many long-lived or idle connections, such as WebSockets, long polling and Server-Sent Events, and for
services that spend their time calling other services. It is a poor fit for CPU-heavy handlers and for code built on
blocking libraries, unless that work is moved off the loop.
This section is for developers who:
-
know Python and want to build real-time or high-concurrency services without a second framework for the networking layer
-
are coming from Flask, Django, FastAPI or Pyramid and want to understand what a single-threaded, single-loop server changes about handlers, databases, tests and deployment
-
maintain Tornado 4.x or 5.x code (callbacks,
@gen.coroutine,IOLoop.instance()) and need the currentasync defidioms and the upgrade path -
need one coherent path from a first handler to WebSockets, security, testing and a multi-process deployment behind nginx
The Bookshelf Live scenario
Every example builds one small original service, Bookshelf Live, so the pages fit together instead of being isolated snippets. It is the real-time companion of the Flask Bookshelf and the FastAPI Bookshelf API, and it shows what Tornado is for:
-
a JSON API for books and reviews backed by an async driver
-
a WebSocket chat room per book, and a "new reviews" feed over long polling and Server-Sent Events
-
cover metadata fetched concurrently from an external service with
AsyncHTTPClient, driven by a bounded queue of workers (a local fake service in tests) -
signed-cookie login, XSRF and cross-origin protection, and Google OAuth 2.0 sign-in
-
tests with
AsyncHTTPTestCase, and deployment as one process per CPU behind nginx
Reading path
The pages are ordered so that each one builds on the previous ones. Read them in this order the first time, then use them as a reference:
-
Foundations: what Tornado is made of, a first running app, why blocking the event loop is the cardinal sin, coroutines, and the queue and lock primitives.
-
The web framework: applications and handlers, routing, error pages, templates and UI modules, static files and translations.
-
Security: signed cookies and login, XSRF and cross-origin protection, and sign-in with third-party providers.
-
HTTP clients, real-time and networking:
AsyncHTTPClient, WebSockets, streaming with long polling and SSE, and the low-level TCP layer. -
Data, configuration and testing: async database drivers, options and logging, and
AsyncHTTPTestCase. -
Production: one process per CPU, nginx, graceful shutdown, serving WSGI apps next to Tornado handlers, and what changed between releases.
The cheat sheet at Tornado Cheat Sheet condenses the whole section onto one page for quick lookup.
What’s covered
Where related material lives elsewhere on this site
The Tornado pages link to existing material instead of repeating it, and cover only what Tornado adds.
| Topic | Where it lives | How the Tornado section relates |
|---|---|---|
The Python language, |
Python Reference, including Concurrency & Async, Virtual Environments & Packaging and Testing |
Tornado pages link here for general Python and cover only the Tornado layer on top of |
Other Python web frameworks |
The introduction compares the frameworks, and the WSGI page shows how to serve a Flask or Pyramid app next to Tornado handlers. |
|
Django Channels and async Django |
The WebSocket and event-loop pages point here for the comparison with Django’s ASGI route. |
|
OAuth 2.0, OpenID Connect, JWT theory |
The third-party authentication page covers only the |
|
Docker and containers |
The deployment page shows only the Tornado-specific one-process-per-container setup. |
|
Kubernetes |
The deployment page shows only graceful shutdown and probes for a Tornado process. |
|
Database engines |
The data page covers only the async drivers and how to wire their pools into handlers. |
|
Messaging and scheduling |
The queue and WebSocket pages point here for work that outgrows an in-process queue or a single process. |
|
CORS |
The XSRF page covers only how to set the headers from a Tornado handler. |
Bibliography
Every source used to prepare this section is listed here, each linked to its official site. Individual pages list the
subset they derive from under their own == References heading.
Official Tornado documentation
Published at tornadoweb.org, grouped as the documentation is:
-
Web framework: tornado.web, tornado.template, tornado.routing, tornado.escape, tornado.locale and tornado.websocket
-
HTTP servers and clients: tornado.httpserver, tornado.httpclient and tornado.httputil
-
Asynchronous networking: tornado.ioloop, tornado.iostream, tornado.netutil, tornado.tcpclient, tornado.tcpserver and tornado.process
-
Coroutines and concurrency: tornado.gen, tornado.locks, tornado.queues and tornado.concurrent
-
Integration with other services: tornado.auth, tornado.wsgi and tornado.platform.asyncio
-
Utilities: tornado.autoreload, tornado.log, tornado.options and tornado.testing
-
Release notes, and the notes of each version used: 3.2.1, 5.0, 5.1, 6.0, 6.2, 6.3, 6.4, 6.5, 6.5.8, 6.5.9 and 6.5.10
-
Development documentation (6.6), including its 6.6.0 release notes and security guide
-
Tornado on GitHub, including the demos chat, file_upload and websocket
-
Jupyter Server on PyPI (a well-known Tornado application)
Libraries and tools used by the pages
-
Python
asynciomodule, in particular runners, coroutines and tasks, event loop, queues, streams and developing with asyncio -
Other Python standard library modules used: concurrent.futures, contextvars, gettext, hashlib.scrypt, logging.config, ssl, unittest, unittest.mock and the warnings filter
-
PyMongo
AsyncMongoClient, its migration guide and the Motor documentation (deprecated) -
pytest and pytest-asyncio
-
Authlib (OAuth and OIDC clients)
-
HTTPX async client and aiohttp (client quickstart), used for comparison
-
Django Channels (comparison)
-
Flask deployment options and Werkzeug
DispatcherMiddleware(WSGI interoperability) -
Pyramid: creating your first app (WSGI interoperability)
Specifications and standards
-
RFC 6455: The WebSocket Protocol and RFC 7692: WebSocket Compression Extensions
-
RFC 6749: The OAuth 2.0 Authorization Framework, RFC 7636: PKCE and OpenID Connect Core 1.0
-
PEP 492: Coroutines with async and await syntax, PEP 3156: Asynchronous IO Support Rebooted: the asyncio module and PEP 3333: Python Web Server Gateway Interface (WSGI)