Building a Modular FastAPI App: Using Git Submodules as Packages
Introduction
As FastAPI projects grow, managing different functionalities within a single repository can become difficult. One way to keep the project modular and maintainable is by using Git submodules.
Git submodules allow you to include other repositories inside your main project. This is useful for adding reusable components like logging, authentication, or utilities while keeping them separate and independently managed.
In this guide, we will cover:
- What Git submodules are
- Why they are useful in FastAPI projects
- How to set up and manage them
- A real-world example using
fastapi-sub-modules
andfastapi-sub-modules-logger-kit
What Are Git Submodules?
Git submodules are repositories within a repository. They allow you to link an external Git repository to your main project while independently keeping its history and updates.
Key Benefits of Git Submodules
- Modularity ~ Keep separate concerns in different repositories.
- Reusability ~ Use the same module across multiple projects without duplication.
- Independent Updates ~ Update submodules without affecting the main project.
- Better Team Collaboration ~ Teams can work on different modules independently.
Understanding Git Submodules in FastAPI
Let’s say we have a main FastAPI project (fastapi-sub-modules
) that includes a logging package (fastapi-sub-modules-logger-kit
) as a Git submodule.
Architecture Overview
The diagram below illustrates the relationship between the main FastAPI repository and its submodule:
fastapi-sub-modules
repository is included fastapi-sub-modules-logger-kit
as a submodule. The logging package is managed separately but linked to the main project.Setting Up Git Submodules in FastAPI
1. Adding a Submodule to Your FastAPI Project
To include a submodule inside your FastAPI project, use:
git submodule add https://github.com/anqorithm/fastapi-sub-modules-logger-kit.git modules/logger-kit
This will:
- Clone the submodule inside
modules/logger-kit
. - Track it as a separate Git repository inside your main project.
fastapi-sub-modules-logger-kit
appears as a submodule inside the main project.2. Cloning a Repository with Submodules
When someone clones your FastAPI project, they won’t automatically get the submodules. To pull them in:
git clone --recurse-submodules https://github.com/anqorithm/fastapi-sub-modules.git
If the repository was cloned normally, initialize and update submodules with:
git submodule update --init --recursive
3. Updating a Submodule
If fastapi-sub-modules-logger-kit
is updated externally, pull the latest changes inside your main project:
cd modules/logger-kit
git pull origin main
Then commit the updated submodule reference in the main repository:
git add modules/logger-kit
git commit -m "chore: updated logger-kit submodule to latest version"
4. Removing a Submodule
To remove a submodule, follow these steps:
git submodule deinit -f modules/logger-kit
git rm -rf modules/logger-kit
rm -rf .git/modules/logger-kit
git commit -m "Removed logger-kit submodule"
This ensures the submodule is completely removed from the main repository.
Example FastAPI Project with Git Submodules
This is a fully working FastAPI project that demonstrates how to use Git submodules to keep your project modular. The example integrates a logging package (fastapi-sub-modules-logger-kit
) as a submodule within the main FastAPI project (fastapi-sub-modules
).
Project Structure
fastapi-sub-modules/
│── modules/
│ ├── logger-kit/ # Git submodule for logging
│── app/
│ ├── routers/
│ │ ├── items.py # API routes
│ ├── main.py # FastAPI app entry point
│── .gitmodules # Tracks submodule reference
│── pyproject.toml # Poetry dependencies
│── README.md
1. Cloning the Project with Submodules
Since fastapi-sub-modules-logger-kit
is included as a Git submodule, clone the repository with:
git clone --recurse-submodules https://github.com/anqorithm/fastapi-sub-modules.git
If you forgot to include the submodules, initialize them manually:
git submodule update --init --recursive
2. Installing Dependencies with Poetry
This project uses Poetry for dependency management. Install dependencies using:
cd fastapi-sub-modules
poetry install
Ensure the logging package is included in pyproject.toml
as a local dependency:
[tool.poetry.dependencies]
python = "^3.12"
fastapi = "^0.104.1"
uvicorn = "^0.24.0"
# Add logger-kit as a local dependency
fastapi-sub-modules-logger-kit = { path = "./logger_kit", develop = true }
3. FastAPI Application
The main.py
file initializes the FastAPI app and integrates the logging submodule.
from fastapi import FastAPI
from .routers import items
from logger_kit import app_logger, RequestLoggingMiddleware
app = FastAPI(title="FastAPI with Submodules")
# Apply middleware to log requests, excluding health checks
app.add_middleware(RequestLoggingMiddleware, exclude_paths={"/health"})
# Include API routes
app.include_router(items.router, prefix="/api/v1", tags=["items"])
@app.get("/")
async def root():
app_logger.info("Root endpoint accessed")
return {"message": "Welcome to FastAPI with Git Submodules"}
@app.get("/health")
async def health_check():
return {"status": "healthy"}
4. Implementing API Routes
The API endpoints use the logging module from the submodule.
from fastapi import APIRouter
from logger_kit import app_logger
router = APIRouter()
@router.get("/items")
async def read_items():
# using the logger for info
app_logger.info({
"action": "fetch_items",
"message": "Retrieving all items"
})
items = ["item1", "item2"]
# using the logger for debug
app_logger.debug(f"Found {len(items)} items")
return {"items": items}
@router.get("/items/{item_id}")
async def read_item(item_id: int):
# using the logger for info
app_logger.info({
"action": "fetch_item",
"item_id": item_id,
"message": f"Retrieving item {item_id}"
})
return {"item_id": item_id}
5. Running the FastAPI Application
Start the FastAPI application using Poetry:
poetry run uvicorn app.main:app --reload
6. Expected Behavior
1. Fetch All Items [GET /api/v1/items]
{
"items": ["item1", "item2"]
}
Log Output:
INFO:logger: {'action': 'fetch_items', 'message': 'Retrieving all items'}
DEBUG:logger: Found 2 items
2. Fetch a Single Item [GET /api/v1/items/42]
{
"item_id": 42
}
Log Output:
INFO:logger: {'action': 'fetch_item', 'item_id': 42, 'message': 'Retrieving item 42'}
7. Updating the Submodule
If the fastapi-sub-modules-logger-kit
submodule gets updated, pull the latest changes:
cd modules/logger-kit
git pull origin main
cd ../..
poetry lock --no-update
poetry install
Conclusion
Using Git submodules in FastAPI projects provides a structured way to keep your code modular, reusable, and easy to maintain. Instead of cluttering your repository with unrelated features, you can separate concerns into independent submodules and manage them efficiently.
Summary:
- Submodules help maintain a clean and modular FastAPI project structure.
- They allow independent updates while remaining linked to the main project.
- They are useful for sharing reusable components like logging, authentication, or database utilities across multiple projects.
By following this approach, your FastAPI app remains organized, scalable, and easier to maintain.
Repositories
- Main FastAPI Project:
fastapi-sub-modules
– A modular FastAPI application using Git submodules.
- Logging Submodule:
fastapi-sub-modules-logger-kit
– A separate logging module integrated into the main project.
Resources
- Main FastAPI Project: https://github.com/anqorithm/fastapi-sub-modules
- Logging Submodule: https://github.com/anqorithm/fastapi-sub-modules-logger-kit/tree/bc5595af66aa47697c3b231227a9fc9313faf8c0
- Git Submodules Documentation: https://git-scm.com/book/en/v2/Git-Tools-Submodules
- FastAPI Official Documentation: https://fastapi.tiangolo.com/
- Poetry Official Documentation: https://python-poetry.org/docs/