1. The callback architecture. I simply freakin' hate the IOLoop. If you have just one asynchronous I/O operation, it's nice and easy. If you have one that depends on another, you have to wrap and curry a callback inside another one. Three? More wrapping and currying. I understand it's pretty much the same in many other platforms like client side AJAX these days. But man, this is Python and we DO have far better alternatives like gevent! You want the epoll() and kqueue() for performance? Fine. But it's Python and you can do it with coroutines without all that asynchronous event handling mess. And minus all those function wrapping and curry, I'm sure it can be much faster, all the while being easier to program with.
2. The Facebook API in auth.py sucks. Just read its source code - it performs all requests by GET - WTF?! It can't even upload files unless you hack it (I've got a branch at http://github.com/martinkou/tornado-upload for that). And look at that _signature function under the FacebookMixin class - it doesn't even use session secrets? I'm not sure if I'm doing anything wrong, and Facebook API's docs don't mention that.. but in my testing, if I just use the application secret key all the way for the signature, Facebook gives me 104 errors. I had to hack it again to make it use session secrets in signing requests.
I don't really care about databases. But last time I checked, psycopg2 has a page telling you how to do async requests with gevent or libevent style coroutines. Tornado? Good luck integrating that with IOLoop and currying your callbacks. Sure you can still make it work, but it's unnecessarily complicated.
Not that "unnecessarily complicated", but Twisted is a lot more mature with respect to coding patterns and has formalized callbacks into a Deferred object that makes it much easier to understand.
- Hard to test, at least relative to Django. There's no built-in support, and being async makes it a little complicated. I have it working now, but it took some bashing and plenty of the mock library.
- Lack of libraries for things we might want to do asynchronously. I can buy the argument that that's fine for databases, but for AMQP it's mandatory. The lack of a (working) Tornado AMQP library drove me to use Cyclone, which is a production-ready port of Tornado to the Twisted framework. Libraries ahoy.
1. Database queries are not asynchronous. This is a big deal for most traditional web applications, and pretty much removes any benefit to using Tornado for them. Even for things that rely mostly on HTTP APIs, there's still a decent chance that you'll want to do authentication or something against a database.
2. It was generally lacking a lot of the maturity and handy declarative syntax you can get with frameworks like Django. There was no ORM, form helpers, etc.
That being said, I really like the idea, performance was great and development seemed to be proceeding at a tremendous pace. The whole project is on GitHub and they seemed very willing to accept both bug-fixes and features.
I like this approach because I prefer writing app logic in a straight line instead of in callbacks. The code is easier to understand and debug.
In Perl there is AnyEvent and luckily CPAN already provides AnyEvent wrappers around pretty much everything!
BTW, There is a (fledging but robust) port of Tornado to Perl: http://search.cpan.org/dist/Tatsumaki/
I've built a few small sites with it, and it's great for experimenting with custom architectures. It doesn't really assume anything about your data or architecture, so you're free to build things on top of it. If you want extra features, they need to come from somewhere else. If you want an integrated solution to knock out a CRUD website in a weekend, you should look at something like Django (which is also fantastic).
I use supervisord for maintaining multiple instances of the application running. I found it the simplest way to manage it. It also gave me support for watching and restarting any instances that hang. I'm also using nginx to proxy. Currently I'm proxying 2 instance of tornado on a 4 core box. I'm also running mongodb, memcached, and nginx on the same small 256MB ram box right now.
In the future I could see me moving to node.js in the future, but for any application that requires working with multiple APIs, Tornado was a much better headstart, and the framework itself was more mature and ready to use than anything from the node.js camp several months ago.
Unfortunately no one is actively supporting the auth portion of Tornado, and it could use a maintainer. I'd set up, but with a newborn I'm not sure when I'll get to it. I'll be releasing ( and have already done so in the past ) any changes I make back to the Tornado project.