Capstone · Weak packet
The Same Initiative, Done Weakly
Nothing below is stupid. Every page is the kind of page a capable senior engineer writes on a Tuesday, and most of it would be approved without comment. That is exactly what makes it worth studying.
Read this the way a reviewer would: not asking “is it wrong?” but “what decision could I make from this, and what would I still have to guess?” Then read the reviewer notes, which put each artifact beside its strong counterpart.
1 Initiative frame · 2 Assumptions · 3 Workflow · 4 Backlog · 5 Acceptance criteria · 6 Non-functional requirements · 7 Architecture · 8 Data model and API · 9 Technical decision · 10 Delivery plan · 11 Ways of working · 12 Test and release plan · 13 Weekly status · 14 Launch summary
1 · Initiative frame
- Background
- Customers are unhappy with our returns process and support is overloaded. Competitors offer self-service returns and we are behind.
- Vision
- Deliver a best-in-class, frictionless self-serve returns experience that delights customers and reduces support load.
- Goals
-
- Launch the self-serve returns portal by the end of Q3.
- Automate return approvals so customers do not wait for an agent.
- Integrate carrier label generation and status notifications.
- Reduce support tickets significantly.
- Improve customer satisfaction.
- Success criteria
-
- Portal launched and available to all customers.
- 90%+ of returns approved automatically.
- Support tickets down.
- Positive customer feedback.
- No P1 incidents in the first month.
- Scope
- Returns request, eligibility check, carrier label, status tracking, email notifications. Admin view for support agents.
- Out of scope
- Anything not listed above.
- Timeline
- 10 weeks. Launch 30 September.
- Stakeholders
- Product, Engineering, Design, Support, Finance, Legal.
- Assumptions and risks
- See section 2.
The brief was reviewed at the kickoff on 24 August and signed off by the steering group. It is version 1.0 and is expected to be stable; changes go through the change-request process.
2 · Assumptions and risks
- Customers want to handle returns themselves rather than contacting support.
- Our returns policy can be expressed as rules in code.
- The carrier API is fast and reliable; it is already used by the warehouse team.
- The order platform exposes everything we need about an order.
- Warehouse receipt events are reliable.
- Support agents will handle the small number of edge cases that cannot be automated.
- Automating approvals will not increase fraud, since the same rules apply.
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Carrier API integration takes longer than expected | Medium | Medium | Start integration early |
| Scope creep | High | Medium | Change-request process |
| Dependency on platform team for credentials | Medium | Low | Raise early |
| Team capacity over the summer holidays | Medium | Medium | Plan around leave |
| Performance under load | Low | High | Load test before launch |
The assumptions were validated with stakeholders at kickoff. Support confirmed that most returns follow standard policy, and the warehouse team confirmed the carrier API works well for them. No further validation is planned; the team will find out during development.
3 · Returns workflow
The new returns flow is straightforward and was agreed with product and support in the kickoff workshop.
- Customer logs in and selects an order to return.
- System checks eligibility against the returns policy.
- If eligible, the system approves the return and generates a carrier label.
- Customer receives the label by email and ships the item.
- Warehouse receives and inspects the item.
- Refund is issued to the original payment method.
- Customer receives a confirmation email.
If the return is not eligible, the customer sees an error message and can contact support. The current process is well understood by the team — it is essentially the same flow with an agent doing steps 2 and 3 manually — so it has not been documented separately.
Domain entities: Return, ReturnItem, Order, Customer, Label, Refund, ReturnStatus.
4 · Backlog
The work has been broken down into user stories and estimated in story points. Everything above the line is MVP for the 30 September launch.
| # | Story | Area | Points |
|---|---|---|---|
| RET-1 | Create returns database schema and models | Backend | 5 |
| RET-2 | Create Return API endpoints (CRUD) | Backend | 8 |
| RET-3 | Implement eligibility rules engine | Backend | 13 |
| RET-4 | Integrate with order platform | Integration | 8 |
| RET-5 | Integrate with carrier API for labels | Integration | 13 |
| RET-6 | Integrate with payments for refunds | Integration | 8 |
| RET-7 | Consume warehouse receipt events | Integration | 5 |
| RET-8 | Build returns request screen | Frontend | 8 |
| RET-9 | Build status tracking screen | Frontend | 5 |
| RET-10 | Build agent admin screen | Frontend | 8 |
| RET-11 | Email notification templates | Frontend | 3 |
| RET-12 | Authentication and authorization | Backend | 5 |
| RET-13 | Set up monitoring and dashboards | Platform | 3 |
| RET-14 | Load testing | Platform | 3 |
| RET-15 | Accessibility review | Frontend | 3 |
| RET-16 | Documentation and runbook | Platform | 2 |
| — MVP line — | |||
| RET-17 | Exchanges instead of refunds | Backend | 13 |
| RET-18 | Guest checkout returns | Backend | 8 |
| RET-19 | International returns | Integration | 13 |
| RET-20 | SMS notifications | Integration | 5 |
Total above the line: 91 points. At a velocity of around 20 points per sprint, that is five sprints, which fits the 10-week timeline.
5 · Acceptance criteria
As a customer I want my return request to be approved automatically so that I do not have to wait for support.
Acceptance criteria
- Given a valid return request, when the customer submits it, then the system checks eligibility and returns a result.
- Eligible returns are approved.
- Ineligible returns are rejected with an appropriate message.
- Errors are handled gracefully.
- The endpoint responds quickly.
- Unit tests cover the rules.
As a customer I want a shipping label so that I can send my item back.
Acceptance criteria
- Given an approved return, when the label is requested, then a label is created and emailed to the customer.
- The label PDF is downloadable from the status page.
- API errors are logged and retried.
- Integration tests use the carrier sandbox.
Further acceptance criteria are captured on the individual tickets and refined in sprint planning. Edge cases will be raised by QA during testing.
6 · Non-functional requirements
| Requirement | Target |
|---|---|
| Scalability | The system must be scalable to handle future growth. |
| Performance | Pages should load quickly; API responses should be fast. |
| Availability | 99.9% uptime. |
| Security | The system must be secure. Follow company security standards and OWASP Top 10. |
| Maintainability | Code must be clean, well tested, and easy to change. |
| Reliability | The system must be reliable and handle errors gracefully. |
| Observability | All services must emit logs and metrics. |
| Accessibility | Meet accessibility standards. |
| Compliance | Comply with data protection requirements. |
These are the standard NFRs for customer-facing systems in our estate and were agreed with the architecture group.
7 · Architecture
The architecture follows our standard patterns: a React frontend, a Python service layer, and managed infrastructure. It is designed to be scalable and cloud-native.
| Component | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite |
| API | FastAPI, Python 3.12 |
| Database | PostgreSQL 16 |
| Cache | Redis |
| Queue | RabbitMQ + Celery |
| Object storage | S3 (label PDFs) |
| Runtime | Kubernetes, 3 replicas, HPA |
| CI/CD | GitHub Actions → ArgoCD |
| Monitoring | Datadog, Sentry |
| Auth | Existing SSO / session service |
The Returns Service talks to:
- Order Service
- Carrier API
- Payment Service
- Warehouse Service
- Notification Service
- Auth Service
[ Frontend ] --> [ Returns API ] --> [ Postgres ]
|
+--> [ Order Service ]
+--> [ Carrier API ]
+--> [ Payment Service ]
+--> [ Redis ]
+--> [ RabbitMQ ] --> [ Celery worker ]
Sequence diagrams for the main flows will be added to the wiki during implementation. The service is deployed as its own microservice so it can be scaled and released independently of the storefront, in line with our microservices strategy.
8 · Data model and API
| Column | Type | Notes |
|---|---|---|
| id | uuid | PK |
| order_id | uuid | FK to order platform |
| customer_id | uuid | |
| status | varchar | pending / approved / rejected / shipped / received / refunded |
| reason | text | free text from the customer |
| label_url | text | nullable |
| refund_amount | numeric | nullable |
| created_at / updated_at | timestamptz |
| Method | Path | Purpose |
|---|---|---|
| POST | /api/v1/returns | Create a return |
| GET | /api/v1/returns/{id} | Get a return |
| GET | /api/v1/returns | List the customer's returns |
| PATCH | /api/v1/returns/{id} | Update a return (status, agent notes) |
| POST | /api/v1/returns/{id}/label | Generate the label |
| POST | /api/v1/webhooks/warehouse | Receive receipt events |
Standard REST conventions. Errors use standard HTTP status codes with a JSON body. Versioned under /v1; breaking changes will go to /v2. Clients should be tolerant readers and ignore fields they do not recognise, so adding fields is safe.
Status transitions are enforced in the service layer. Refunds are triggered when the status becomes received. Retries are handled by Celery's built-in retry mechanism.
9 · Technical decision
- Status
- Accepted
- Context
- Calling the carrier API synchronously inside the request could make the request slow if the carrier is slow. We want the API to stay responsive.
- Decision
- We will generate labels asynchronously using RabbitMQ and Celery. When a return is approved, a task is queued; the worker calls the carrier API and updates the return with the label URL. Celery's retry mechanism handles transient failures.
- Rationale
- RabbitMQ and Celery are already part of our standard stack, the team knows them well, and this is the established pattern for background work in our platform. It decouples the request from the carrier and lets us scale workers independently.
- Consequences
- Labels are not available immediately; the frontend will poll the status endpoint. We will need to monitor the queue.
Other decisions (framework choice, database, deployment target) follow existing platform standards and did not require an ADR.
10 · Delivery plan
| Sprint | Focus | Stories |
|---|---|---|
| 1 | Foundations: schema, models, project setup, auth | RET-1, RET-2, RET-12 |
| 2 | Core backend: eligibility rules, order integration | RET-3, RET-4 |
| 3 | Integrations: carrier, payments, warehouse events | RET-5, RET-6, RET-7 |
| 4 | Frontend: request, status and admin screens, emails | RET-8, RET-9, RET-10, RET-11 |
| 5 | Hardening: monitoring, load test, accessibility, docs, UAT | RET-13 – RET-16 |
- Platform team: carrier sandbox credentials. Raised in the platform channel; awaiting response.
- Payments team: refund API access. Ticket raised.
- Warehouse team: event stream access. Ticket raised.
- Legal/Privacy: data protection review. Will be requested before launch.
Estimated completion: 5 sprints from 24 August, ending 30 September. The plan is achievable with the current team. Buffer for unknowns is built into the hardening sprint.
11 · Ways of working
- Team: 1 PM, 1 designer, 1 tech lead, 4 engineers.
- Ceremonies: daily standup (15 min), sprint planning, backlog refinement, sprint review, retrospective.
- Board: Jira. Definition of Done: code reviewed, tests written, deployed to staging, PO accepted.
- Code review: all pull requests reviewed by the tech lead before merge.
- Communication: Slack channel, weekly status email to stakeholders.
- Decisions: we work as one team and decide together; anything contentious goes to the tech lead or the PM.
- Documentation: Confluence space for the project.
The team is collaborative and everyone is encouraged to contribute to any decision. Escalation is to the engineering manager if needed.
12 · Test and release plan
- Unit tests, minimum 80% coverage (enforced in CI).
- Integration tests against the carrier sandbox and a test order platform.
- End-to-end tests for the main journeys (Playwright).
- Load test before launch: 100 requests/second for 10 minutes.
- Accessibility scan (axe) as part of RET-15.
- QA sign-off and UAT with support agents in sprint 5.
- Security scan (SAST/dependency) in CI.
- Datadog dashboard: request rate, error rate, p95 latency, CPU, memory, queue depth.
- Sentry for exceptions.
- Alerts: error rate above 5% for 5 minutes, p95 latency above 2 s, pod restarts.
- PagerDuty rotation: existing platform on-call.
- Deploy to staging at the end of each sprint.
- UAT with support agents in sprint 5.
- Deploy to production behind a feature flag (
returns_portal_enabled), disabled. - Smoke test in production with internal accounts.
- Enable the flag for 100% of customers on launch day, 30 September.
- Monitor the dashboard for the first week.
- If there is a serious problem, disable the flag or roll back the deployment.
13 · Weekly status
- Status
- Green — on track for 30 September.
- Progress this week
-
- Sprint 2 completed: 22 of 24 points delivered (velocity 22).
- Eligibility rules engine implemented and unit tested.
- Order platform integration complete.
- Carrier integration started — approximately 80% complete.
- Database schema finalised and migrated on staging.
- 12 tickets closed, 3 in progress, 1 blocked.
- Design handed over the status page and admin screens.
- Next week
- Finish carrier integration, start payments and warehouse events, begin frontend work.
- Risks and issues
-
- The carrier sandbox is slower than expected. The team is investigating and will optimise if needed.
- Still waiting on the payments team for refund API access. Chased again this week.
- Support mentioned that a lot of returns are actually gift orders. Noted for later.
- Blockers
- None that will affect the date.
- Metrics
- Velocity 22. Burn-down on track. Test coverage 84%. Zero open P1 bugs.
- Asks
- None.
Sprint 3 will absorb the remaining carrier work. The team is confident that the 30 September date holds.
14 · Launch summary
- Status
- Launched on 29 September, one day ahead of plan. All MVP stories delivered.
- What shipped
- Self-serve returns portal with automated eligibility, carrier label generation, status tracking, email notifications, and an agent admin screen.
- Results
-
- Portal is live for 100% of customers.
- Most returns are now approved automatically.
- Support has reported a noticeable drop in returns-related tickets.
- No P1 incidents in the first two weeks.
- Positive feedback from the support team and from the steering group.
- Retrospective
-
- What went well: strong team collaboration; hit the date; good test coverage; the async label design worked.
- What could be better: the carrier integration took longer than estimated; requirements changed mid-project; too many meetings.
- Actions: estimate integrations more conservatively; tighten the change-request process.
- Next steps
- Phase 2: exchanges, guest checkout, international returns, SMS notifications. Backlog already groomed (RET-17 to RET-20). The team rolls straight onto phase 2 in October.
- Thanks
- Great effort from everyone involved.
The feature flag remains in place for safety. Monitoring is on the existing platform dashboard. Documentation is in Confluence.
- Write down the three sentences in this packet you would have accepted without question a year ago.
- For each of the fourteen sections: what decision could a reader actually make from it, and what would they still have to guess?
- Which single change to this packet would improve it most — and which artifact would that change force you to rewrite next?
Now read the reviewer notes, which put each section beside its strong counterpart and name the rubric dimension the difference touches.