API Framework and Libraries
Status: Active
Last Modified: 2023-07-07
Related Issue: #28
Deciders: Lucas brown, Aaron Couch, Billy Daly, Sammy Steiner, Daphne Gold, Gina Carson, Sumi Thaiveettil, Eshter Oke
Context and Problem Statement
This ADR is to decide what python framework to use for the back-end API of grants.gov. Python was chosen as the language for the back-end API in ADR #3.
Decision Drivers
Is this framework well established with a broad community of developers
Does it have good documentation for developers to get up to speed quickly
Does this language have a track record for reliability and continued support
How familiar is Nava and HHS with the framework
How effectively can the chosen framework support the back-end needs of grants.gov
Options Considered
Flask
Flask + Connexion
Flask + APIFlask
FastAPI
Django
Decision Outcome
Chosen option: Flask + APIFlask, because it is well established with a broad community of developers and provides good tooling to move quickly. It has great documentation to help folks contribute quickly. Additionally the Nava Flask template recently adopted it, so we can leverage the template to get going quickly with a well engineered solution.
Positive Consequences
Leverages the Nava open source template
OpenAPI specs can be auto generated from models in code
Flexibility in defining schemas
Negative Consequences
Code first paradigm, we should auto generate api documentation in the CI/CD pipeline to ensure it stays up to date with the code
This is a relatively new library, so we should ensure code modularity in case we need to swap it out in the future
Pros and Cons of the Options
Flask
Flask is a simple, but extensible, micro web framework for python created in 2010 that is easy to learn and build with. While it is capable on its own, it relies on other libraries to add core functionality. It was written to be pythonic, meaning it leverages python's unique features and follows python's principles of being readable and maintainable. Flask depends on the Werkzeug WSGI toolkit, the Jinja template engine, and the Click CLI toolkit.
Pros
Shallow learning curve, great documentation, and pythonic style makes it easy for contributors to support
Flexible and scalable microframework means it can adjust as the needs of the project changes
Designed for back-end API services
Cons
Tech stack can get complicated over time with various libraries
Lack of standardization means more decision making and good code quality is very important
Async operation takes additional planning and work
Flask + Connexion
This deserves its own option because it fundamentally changes the way that we would develop with python and flask. With connexion, you first write your API contract, using the Swagger/OpenAPI standard. Then, the endpoints you defined will be mapped to your python view functions, ensuring that your python code does what your API contract says it does. This makes it rather unique in the landscape of python web frameworks, as most other tools start from your code instead of the other way around.
Pros
Same as Flask
API first means all teams can work with a single contract, instead of having multiple sources of truth
Documentation in OpenAPI or Swagger means it's easier to understand and integrate with other tools
Cons
Same as Flask
Flask + APIFlask
This deserves its own option because it adds a lot of support to Flask for a more traditional code first api approach, in contrast to connexion. APIFlask is a lightweight Python web API framework based on Flask and marshmallow-code projects. It's easy to use, highly customizable, ORM/ODM-agnostic, and 100% compatible with the Flask ecosystem. The Nava Flask template repo has recently replaced connexion with apiflask, documented in connexion replacement decision record.
APIFlask relies on Marshmallow to define the request & response schemas. Marshmallow is a well tested serialization/deserialization, and validation library for converting between JSON and python dictionaries. Marshmallow schemas are defined using classes in-code, and polymorphism can be used to quickly make small adjustments to schemas for new endpoints. Fields can be marked as just for serialization or deserialization (ie. response / request) which also minimizes how much needs to be defined. Marshmallow also supports the concept of "partial" schemas. When attaching a schema to a route, if you mark it as partial, all fields are marked as not required. This makes building schemas for update endpoints simpler as you don't need to duplicate an entire schema just to mark fields as optional. This means we can potentially define a single schema for create, read, and update endpoints, and avoid a significant amount of duplication.
APIFlask uses apispec to convert the Marshmallow schema into the OpenAPI/Swagger specification.
Pros
Same as Flask
Simplifies boilerplate code necessary for a Flask API by pulling the best features of many libraries
Very well documented
Marshmallow is very flexible, and allows for significant customization in defined schemas
Cons
Same as Flask
Marshmallow only converts JSON to dictionaries - if you want to work with typed/IDE auto-complete-able objects, you'll need to use a library like Pydantic and define models again
Relatively young project
FastApi
FastAPI is a modern, fast (high-performance), web framework created in 2018 for building APIs with python 3.7+ based on standard python type hints. This implementation-first library is designed as a performant and intuitive alternative to existing python API frameworks.
Schemas are defined using Pydantic which is a model definition and validation library that thoroughly leverages Python typing features
Pros
Designed for speed and can perform asynchronous operations natively (if needed)
Can generate OpenAPI or Swagger documentation from the code
Cons
FastAPI maintenance and updates can be sporadic and have long spans between them, maintained by a single person
Documentation for more advanced cases is lacking
As the newest of the frameworks, it has the smallest community of support
Can have memory management issues
Django
Django is a full stack python web framework created in 2005 that follows the model–template–views (MTV) architectural pattern. It is maintained by the Django Software Foundation (DSF), an independent organization established in the US as a 501(c)(3) non-profit. Django is well documented and includes everything you may need in a full stack application already installed.
Pro
Maintained by an independent 501(c)(3) non-profit organization
Longest running and most popular python framework in consideration
Cons
Monolithic style, steep learning curve, and large codebase make it difficult for collaborators
Assumes both front end and back end are included in the monolith application
Links <!-- OPTIONAL -->
Last updated