This document records the resolution status of production-readiness gaps identified during development. It includes items that were fully resolved, partially resolved, and intentionally deferred with documented rationale. The goal is to preserve engineering tradeoffs transparently rather than leaving them only in code comments.
| # | Item | Flagged in | Status | Resolution |
|---|---|---|---|---|
| 1 | No automated tests beyond auth-service |
Phase 17 | ✅ Resolved | Test suites added for tracking-service, search-service, and analytics-service (Step 2). |
| 2 | scraper-service runs as root in Docker |
Phase 12 | ✅ Resolved | Dedicated scraperuser, explicit $HOME, and ownership configured for cache/profile directories; --no-sandbox is retained deliberately as a separate browser-sandbox concern. |
| 3 | Postgres/Redis/RabbitMQ run as Deployments, not StatefulSets | Phase 14 | ✅ Resolved | Converted to StatefulSets with stable network identity (Step 4). |
| 4 | Kubernetes Secrets are base64-encoded, not encrypted at rest | Phase 14 | Documented as a known limitation; full resolution requires cloud KMS integration or Sealed Secrets (Step 5). | |
| 5 | CELERY_BROKER_URL embeds password in ConfigMap, not Secret |
Phase 14 | ✅ Resolved | Moved to Secret and composed at runtime (Step 5). |
| 6 | No rate limiting on search-service |
Phase 6/9 (implicit) | ✅ Resolved | Per-IP rate limiting added (Step 6). |
| 7 | No structured or correlated logging across services | All phases | Implemented in analytics-service and tracking-service to establish the pattern and end-to-end correlation. auth-service and search-service still require the same mechanical 3-file update: logging_config.py, middleware wiring in main.py, and outgoing-call header propagation. |
|
| 8 | Frontend bundle size warning (630KB) | Phase 11 | ✅ Resolved | React.lazy and dynamic import() isolate recharts into a separate chunk. Main bundle reduced from 630KB to 264KB; chart chunk loads only when a user views a price trend. |
| 9 | No zero-downtime migration strategy | Phase 17 | A breaking-schema migration has not been introduced yet. The correct approach is the expand/contract pattern, which is documented here for future use. | |
| 10 | GitHub Actions deploy workflow needs a real cloud cluster | Phase 17 | The workflow is ready for a real Kubernetes cluster, but end-to-end deployment validation requires external cloud infrastructure, which is outside the scope of this student project. |
All migrations written so far have been additive, such as new tables or new columns with safe defaults. That means the current alembic upgrade head flow is safe for the schema changes already introduced.
A genuinely breaking migration would require the expand/contract pattern:
- Add the new schema alongside the old one.
- Deploy code that writes to both paths and backfill data.
- Switch reads to the new schema.
- Remove the old schema in a final cleanup migration.
This is a real production pattern, but it has not been demonstrated yet because the project has not needed a deliberately breaking schema change.
The deploy.yml workflow is written to work with a real Kubernetes cluster such as GKE, EKS, or AKS. The only missing piece is a cluster-specific kubeconfig secret, which requires actual cloud infrastructure to generate.
This is intentionally left as an external-dependency item rather than simulated with a mock cluster, because a fake environment would not validate the real deployment path.
This tracker is not a claim that PriceLens is ready for real paying users at scale -- it's a claim that the specific, named gaps identified during development have been resolved or honestly documented, and that the reasoning behind every remaining gap is explicit rather than hidden. A real production system serving real traffic would need, at minimum: load testing to validate the resource requests/limits from Phase 14 are actually correctly sized, a real TLS/domain setup for the Ingress, an incident response runbook, and on-call alerting wired to the Prometheus metrics from Phase 15 (currently visualized in Grafana but not alerting anyone). These are accurately scoped as beyond a learning project, not silently assumed to be unnecessary.