01 / Data & analytics
Compare prices, not spreadsheets
Price monitoring for a retail chain: product comparison, match review and price history in one place.
The task
Pricing decisions need a like-for-like view of competitors. Product names differ, and prices vary by store and region.
What we built
The system collects offers and suggests matching products. A person reviews each match before it is used in comparisons, price history and Excel reports.
Price collection implemented for four competing retailers in one workflow
Only approved product pairs enter reports
Own prices and stock imported from the catalogue

More product screens



How it works
- Collection & normalization
Adapters collect competitor prices, availability, and promotions per store and region, and bring them into a common format without re-saving duplicate observations.
- Matching
The algorithm proposes candidate matches between our product and a competitor product based on text and structural similarity.
- Manual review
An operator confirms or rejects the proposed match; only confirmed pairs are used in reports.
- Analytics & reporting
Confirmed comparisons form the price position and history, available in the interface and exportable to Excel.
Try it
Is this the same product?
Review the suggested pairs. This demo uses fictional data. Your choices are not saved or sent anywhere.
- Whole milk, 1 LWhole milk, 1000 mLSimilarity96 / 100
- Coffee beans, 250 gGround coffee, 250 gSimilarity88 / 100
- Black tea, 25 bagsBlack tea, 50 bagsSimilarity74 / 100
- Still water, 0.5 LNon-sparkling water, 500 mLSimilarity69 / 100
For your technical team: inside the solution
A web application, a background worker, and a scheduler run as separate processes around a shared database; competitor adapters plug into one common contract, while the own assortment arrives through a separate protected import.
- Web application and server-rendered interface
- Background worker and scheduler
- Competitor data collection adapters
- Own-assortment import
Reliability
- Separate web, worker, and scheduler processes with recovery of unfinished jobs after a restart.
- User roles, an audit log, and brute-force login protection.
- A defined backup and update procedure before any schema change.
- Security headers and a content security policy are enforced at the application level, not left to web-server configuration.
Decisions and trade-offs
Only a manually confirmed match is used in working reports.
Automated product matching can be wrong and distort business analytics.
Automation speed is not traded for the accuracy of the data decisions rely on.
Current state and price history are stored separately.
Current prices need to be shown quickly while price history must still be preserved.
Analytics stays fast without losing the change history.
Own-price import is idempotent by batch identifier.
A client system may resend the same price batch after a network error.
A repeated request cannot create duplicate or conflicting data.
Collection concurrency is controlled separately per source.
Several competitor sources cannot be collected the same way without risking overload or blocking.
Data collection does not put unnecessary load on competitor sources.
Automatic confirmation is disabled entirely: every candidate match, regardless of its score, waits for an operator decision.
A high similarity score from the algorithm does not guarantee it is genuinely the same product.
No automated matching result reaches the reports without a human decision.
A confirmed match applies at the competitor level as a whole, not per individual store.
Verifying a match separately for every competitor store and region would make manual review unworkable as the network grows.
Manual review scales across many store locations without a proportional increase in operator workload.
Technologies
- Python
- Flask
- PostgreSQL
- SQLAlchemy / Alembic
- RapidFuzz
- Chart.js
- Gunicorn / Nginx / systemd