Case study
Household Inventory Tracker
A small system, evolved deliberately.
What the system does
A clear record of what is there and how it is tracked.
Household Inventory Tracker keeps household items structured and accessible: what an item is, where it is stored, and whether it is managed as a quantity or as an individual asset.
Consumable supplies can be tracked with a current and minimum quantity. A distinct household tool can instead be recorded as an individual item without stock quantities.
The system can be used through a console application or a REST API, with both working from the same PostgreSQL-backed inventory.
Growth through justified stages
Each turning point introduced a new system concern.
The releases form a progression from core behaviour to persistence, additional access, repeatability and stronger operational safeguards—not a list of technologies added for their own sake.
v0.1.0
Establish the behaviour
The project began as a console application with JSON persistence and initial tests, keeping the first release focused on inventory behaviour.
v0.2.0–v0.3.0
Create a shared data foundation
PostgreSQL became the runtime source of truth, then a REST API was added while the console application remained available.
v0.4.0–v0.5.0
Make development repeatable
Docker Compose brought the API and PostgreSQL into a repeatable local environment. GitHub Actions then automated Python tests, PostgreSQL integration tests and Docker image build validation.
v0.6.0–v0.7.0
Strengthen the domain and startup
Tracking modes introduced migrations, validation, database constraints and expanded tests. Health checks, readiness-based startup and first-run schema initialization made local startup more explicit.
v0.8.0
Add controlled query capability
The API gained literal case-insensitive search, approved sorting, low-stock filtering and bounded pagination.
Planned
Next stage
Azure deployment is the next cloud-learning and deployment stage.
Two interfaces, one shared system
Different ways in, the same data underneath.
The console and REST API keep their interface-specific responsibilities, then converge on the same repository, database connection layer and PostgreSQL inventory.
Console interface
app.pyinventory_workflows.py
REST API
- FastAPI
- routers / dependencies
item_service.py
Shared data layers
item_repository.pydatabase.py- PostgreSQL
app.py and inventory_workflows.py. The REST path runs through FastAPI, its routers and dependencies, and item_service.py. Both then use item_repository.py, database.py and PostgreSQL.Engineering decisions visible in the code
Evidence of how the system is kept understandable.
Preserve useful interfaces
Adding another way into the system did not require discarding the working console application.
Repository evidenceFastAPI added a REST interface while both paths continued to use shared PostgreSQL-backed repository and database layers.
Enforce domain rules at multiple boundaries
Rules about how an item is tracked are protected where data enters the application and where it is stored.
Repository evidenceTracking modes are supported through Pydantic validation, sequential migrations, PostgreSQL constraints and tests across the stack.
Control external input
Flexible queries remain bounded by explicit choices rather than being passed unchecked into the database.
Repository evidencePsycopg queries are parameterized, search characters are escaped literally, sorting is allowlisted and pagination limits are validated.
Treat failure and startup as system concerns
The system defines how expected failures are communicated and how dependent services become ready.
Repository evidenceThe API returns controlled 404, 422 and 503 responses; Docker adds health checks, readiness-based startup and first-run schema initialization.
Automate verification
Checks cover isolated behaviour as well as the places where the application meets PostgreSQL and its container image.
Repository evidenceGitHub Actions runs Python tests, isolated PostgreSQL integration tests and Docker image construction checks.
Current state and next direction
Useful evidence, with its boundaries made clear.
Current · v0.8.0
A working local-development system
The current release has console and REST interfaces, PostgreSQL persistence, Docker-based local development, automated CI, quantity and individual tracking modes, and API querying.
Next · Planned
Azure deployment and cloud learning
HIT is not currently production-deployed. Its Docker configuration supports local development, and Azure remains the next planned deployment stage.
What this demonstrates
- Working software can be extended without discarding useful interfaces.
- Domain rules belong at appropriate application and database boundaries.
- New capability should arrive with proportionate validation and testing.
- Startup, configuration and failure handling are part of system design.
- Query flexibility can be added without accepting uncontrolled input.
Start a conversation
Tell me what isn’t working.
You do not need to know what the technical solution should be. Start with the process, information or system that feels harder to work with than it should.
Discuss a problem