Simple e-commerce backend API built with FastAPI, SQLAlchemy, Alembic, PostgreSQL, Docker Compose, and Pytest.
The project allows managing:
- clients;
- products;
- warehouses;
- stock;
- orders.
.
├── Makefile
├── README.md
├── app
│ ├── Dockerfile
│ ├── Makefile
│ ├── data
│ ├── migrations
│ ├── scripts
│ ├── src
│ └── tests
└── docker
├── compose-prod.yml
├── compose-test.yml
└── postgres.conf
Main application source code.
src
├── api
├── config
├── infrastructure
├── main.py
├── models
├── repositories
└── services
api— FastAPI routers, schemas, dependencies, middlewares and error handlers.config— application settings from environment variables.infrastructure— database engine and session configuration.models— SQLAlchemy database models.repositories— database query layer.services— business logic, for example order creation.main.py— application entry point.
Alembic migrations for database schema changes.
Automated tests for API endpoints and business logic.
Docker Compose files for production-like and test environments.
Create production env file:
cp docker/.env.example docker/.envExample docker/.env:
# Service
SERVICE__NAMESPACE=web-app
SERVICE__NAME=web-app
SERVICE__VERSION=0.1.0
SERVICE__STAGE=local
# PostgreSQL
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres_password
POSTGRES_DB=ecommerce
POSTGRES_PORT=5432
# PgBouncer
PGBOUNCER_PORT=5433Start the project:
make prodOpen API documentation:
http://localhost:8000/docs
Create test .env.test file or you can use ready files
touch docker/.env.testExample docker/.env.test:
# Service
SERVICE__NAMESPACE=test-web-app
SERVICE__NAME=test-web-app
SERVICE__VERSION=0.1.0
SERVICE__STAGE=test
# PostgreSQL
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres_password
POSTGRES_DB=ecommerce_test
POSTGRES_PORT=5432touch app/.env.testExample app/.env.test:
# App
DEBUG=True
# Service
SERVICE__NAMESPACE=web-app
SERVICE__NAME=web-app
SERVICE__VERSION=0.1.0
SERVICE__STAGE=local
# Database via PgBouncer
DATABASE__URI=postgresql+asyncpg://postgres:postgres_password@localhost:5432/ecommerce_test
DATABASE__POOL_SIZE=30
DATABASE__MAX_OVERFLOW=15
DATABASE__POOL_TIMEOUT=120
DATABASE__POOL_RECYCLE=900Run tests:
make testThis command starts the test database, waits until it is ready, runs tests with coverage, and then stops the test environment.
make prod # start production-like environment
make test # run tests with Docker test database
prod-clear # down docker composedocker compose --env-file docker/.env -f docker/compose-prod.yml up -d dbcp app/.env.example app/.envExample app/.env:
# App
DEBUG=True
# Service
SERVICE__NAMESPACE=web-app
SERVICE__NAME=web-app
SERVICE__VERSION=0.1.0
SERVICE__STAGE=local
# Database via PgBouncer
DATABASE__URI=postgresql+asyncpg://postgres:postgres_password@localhost:5432/ecommerce
DATABASE__POOL_SIZE=30
DATABASE__MAX_OVERFLOW=15
DATABASE__POOL_TIMEOUT=120
DATABASE__POOL_RECYCLE=900cd ./app
make start-api-devThe project uses a layered structure:
router -> service -> repository -> database
Routers handle HTTP requests and responses. Repositories contain database queries. Services contain business logic, such as creating orders, checking stock availability, and calculating totals. This approach keeps the code easier to test, maintain, and extend.