logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

Why-I-built-sr.ht-with-Flask.md (4351B)


  1. ---
  2. date: 2019-01-30
  3. # note to self: shoot David Lord <davidism@gmail.com> an email when this is
  4. # ready (2019-01-08)
  5. layout: post
  6. title: Why I chose Flask to build sr.ht's mini-services
  7. tags: ["flask", "sourcehut", "web"]
  8. ---
  9. [sr.ht](https://sr.ht) is a large, production-scale suite of web applications (I
  10. call them "mini-services", as they strike a balance between microservices and
  11. monolithic applications) which are built in Python with
  12. [Flask](http://flask.pocoo.org/). David Lord, one of the maintainers of Flask,
  13. reached out to me when he heard about sr.ht and saw that it was built with
  14. Flask. At his urging, I'd like to share the rationale behind the decision and
  15. how it's turned out in the long run.
  16. I have a long history of writing web applications with Flask, so much so that I
  17. think I've lost count of them by now - at least 15, if not 20. Flask's
  18. simplicity and flexibility is what keeps bringing me back. Frameworks like
  19. Django or Rails are much different: they are the kitchen sink, and then some. I
  20. generally don't need the whole kitchen sink, and if I were given it, I would
  21. want to change some details. Flask is nice because it gives you the basics and
  22. lets you build what you need on top of it, and you're never working around a
  23. cookie-cutter system which doesn't cut your cookies in quite the way you need.
  24. In sr.ht's case in particular, though, I have chosen to extend Flask with [a new
  25. module][core.sr.ht] common to all sr.ht projects. After all, each service of
  26. sr.ht has a lot in common with the rest. Some of the things that live in this
  27. core module are:
  28. [core.sr.ht]: https://git.sr.ht/~sircmpwn/core.sr.ht
  29. - Shared jinja2 templates and stylesheets
  30. - Shared rigging for [SQLAlchemy](https://www.sqlalchemy.org/) (ORM)
  31. - Shared rigging for [Alembic](https://alembic.sqlalchemy.org/en/latest/)
  32. - [A little validation module][validation.py] I'm very proud of
  33. - API behavior, webhooks, OAuth, etc, which are consistent throughout sr.ht
  34. [validation.py]: https://git.sr.ht/~sircmpwn/core.sr.ht/tree/master/srht/validation.py
  35. The mini-service-oriented architecture allows sr.ht services to be deployed
  36. ala-carte for users who only need a fraction of what we offer. This design
  37. requires a lot of custom code to integrate all of the services with each other -
  38. for example, all of the services use a single shared config file, which contains
  39. both shared config options and service-specific configuration. sr.ht also uses a
  40. novel approach to authentication, in which both user logins and API
  41. authentication is delegated to an external service, meta.sr.ht, requiring
  42. further custom code still. core.sr.ht additionally provides common SQLAlchemy
  43. mixins for things like user tables, which have many common properties, but for
  44. each service may have service-specific columns as well.
  45. Django provides their own ORM, their own authentication, their own models, and
  46. more. In order to meet the design constraints of sr.ht, I'd have spent twice as
  47. long ripping out the rest of Django's bits and fixing anything that broke in the
  48. resulting mess. With Flask, these bits were never written for me in the first
  49. place, which gives me the freedom to implement this design greenfield. Flask is
  50. small and what code it does bring to the table is highly pluggable.
  51. Though it's well suited to many of my needs, I don't think Flask is perfect. A
  52. few things I dislike about it:
  53. - First-class [jinja2](http://jinja.pocoo.org/) support is probably out of
  54. scope.
  55. - flask.Flask and flask.Blueprint should be the same thing.
  56. - I'm not a fan of Flask's approach to configuration. I have a better(?) config
  57. module that I drag around to all of my projects.
  58. And to summarize the good:
  59. - It provides a nice no-nonsense interface for requests, responses, and routing.
  60. - It has a lot of nice hooks for adding your own middleware.
  61. - It doesn't do much more than that, which means you're free to choose and
  62. compose other tools to make up the difference.
  63. I think that on the whole it's quite good. There are frameworks which are
  64. smaller still - but I think Flask hits a sweet spot. If you're making a
  65. monolithic web app and can live within the on-rails Django experience, you might
  66. want to use it. But if you are making smaller apps or need to rig things up in a
  67. unique way - something I find myself doing almost every time - Flask is probably
  68. for you.