Operations Platform

User ID Management

Bulk Reporting

User Roles

Alerts & Notification

Operations Platform

User ID Management

Bulk Reporting

User Roles

Alerts & Notification

Operations Platform

User ID Management

Bulk Reporting

User Roles

Alerts & Notification

Client:

Government Agency

Workstream 02

Bulk Reporting Enhancements

Eliminated 58% of duplicate report submissions and reduced "where is my report?" support tickets by 41% by introducing a canonical 7-state lifecycle model, real-time WebSocket progress visibility, and a 4-step modal that reduced report configuration abandonment by 40%.

The Problem

The IWMS platform generated reports for thousands of assets, users, and compliance events. These bulk operations ran asynchronously—but the system gave users no visibility into what was happening. Reports were submitted into a black box. Users couldn't distinguish between "processing," "queued," "failed," or "still running from 20 minutes ago."

The consequence: users resubmitted the same report repeatedly out of uncertainty, creating system overload and queue congestion. Operations managers couldn't plan downstream work around report completion. "Where is my report?" was the #2 support ticket category—a user experience failure masquerading as a process problem.

My Role

Lead UX Designer

State model + UI design

Timeline

4 months

Discovery through handoff

Collaborators

Cross-functional

PM, 3 engineers, ops team, support

Volume

100K+ reports/day

Across all client orgs

Constraints

Technical: WebSocket support wasn't available for all report types; non-critical operations had to fall back to polling

Regulatory: Complete audit trails required for compliance (SOX, SEC)—report metadata could not be deleted

Performance: 100K+ daily reports couldn't all load at once — virtual scrolling and server-side filtering required

Terminology: Three internal teams used different words for the same statuses — alignment required facilitated workshops

Impact

58%

Fewer duplicate report submissions

41%

"Where is my report?" tickets eliminated

85%

Reduction in API polling load

40%

Fewer abandoned report configurations

Research & Insights

Three findings that directly shaped the system design

Research Finding

Session analysis showed users returned to the reports list an average of 4.3 times while waiting for a single long-running report. For reports taking 30+ minutes, resubmission rate was 67% — users concluded the first submission had failed or was lost.

Method: Session recording analysis (n=200 sessions) + server-side duplicate detection

Insight

Users weren't impatient—they were uncertain. Without progress visibility, they had no signal to differentiate "still working" from "silently failed." The 67% resubmission rate wasn't impatience; it was a rational response to an opaque system. The solution wasn't to make reports faster — it was to reduce uncertainty while they ran.

Design Decision

WebSocket real-time progress + ETA estimation. Even when we couldn't make reports faster, showing percentage complete with a time estimate dramatically reduced uncertainty. Collaborated with engineering on a WebSocket connection that broadcasts progress every 5 seconds. Users could close the page and trust the system would notify them.

Research Finding

Stakeholder interviews across 3 teams (engineering, operations, support) revealed they used 6 different terms for the same report states. Engineering used "Queued/Running/Done." Operations said "Pending/Processing/Completed." Support said "In Queue/Active/Finished." Users saw all three vocabularies in different parts of the UI.

Method: Terminology audit across 3 teams + UI copy inventory (14 status variants found)

Insight

Terminology inconsistency isn't cosmetic—it's a cross-team communication failure. When users called support saying "my report is still processing," support couldn't tell if the user meant "Queued," "Running," or "Finalizing" in the backend system. Mismatched vocabulary compounded every support interaction. Alignment on a single canonical model would reduce support handle time by removing interpretation overhead.

Design Decision

Facilitated a cross-team terminology workshop to define a single canonical 7-state model. I drove this as a UX exercise, not an engineering one—the language users see had to start from user mental models, not backend state names. The resulting glossary became a contract between teams. All UI copy, API response labels, and support documentation aligned to the same vocabulary.

Research Finding

Task analysis showed 31% of report configuration sessions were abandoned before submission. The abandonment pattern was clustered at the filter configuration step—a single-screen form with 14+ fields shown simultaneously. Users either submitted with incomplete filters (leading to incorrect reports) or gave up.

Method: Funnel analysis on report creation flow + exit survey (n=47 responses)

Insight

The 14-field form wasn't complex because reports are complex—it was complex because the form made no distinction between required decisions (report type, date range) and optional refinements (advanced filters). Users faced peak cognitive load at the step with the most optionality. Progressive disclosure would reduce perceived complexity without reducing capability.

Design Decision

4-step multi-step modal with API-backed partial saves. Step 1: report type (required, 4 choices). Step 2: data scope and date range (required). Step 3: optional filters (default to "all"). Step 4: scheduling (if recurring). Each step is independently completable. Partial saves meant users who abandoned could return to a draft in progress.

Key Decisions & Tradeoffs

The choices that shaped the system — including what I explicitly didn't build

1

7 states vs. a simpler 3-state model — granularity in service of compliance

Options Considered

A.

3-state: Pending / Processing / Complete (simple, easy to explain)

B.

7-state canonical model — full lifecycle visibility

Why Option B

Operations teams needed to distinguish Suspended (temporary, reversible) from Deactivated for compliance reporting. Support needed to tell users whether they were "Queued" (not started yet) vs. "Processing" (actively running) — same advice to a user differs based on which state they're in. 3 states collapsed distinctions that users and compliance auditors needed.

Tradeoffs

Higher engineering implementation cost (7 state transitions vs. 3)

More complex onboarding for new users — mitigated with status tooltips on hover

Adopted platform-wide for all async operations — status system became a shared standard

2

WebSocket push vs. polling — accepting technical complexity for UX quality

Options Considered

A.

Client polling every 30s (simpler, no infrastructure change)

B.

WebSocket push for real-time progress — higher quality, more infrastructure

C.

Email-only notification when complete (no in-app progress)

Why Option B

Research showed users polled the page themselves every 2–3 minutes. Polling every 30s wouldn't change behavior. WebSocket allowed progress every 5 seconds — enough granularity to feel live. Email-only (Option C) was insufficient for short-running reports (<5 min). The infrastructure cost was justified by the 58% duplicate reduction it enabled.

Tradeoffs

WebSocket not supported for all report types — non-critical reports fell back to 30s polling with a "checking for updates" indicator

85% reduction in API polling load — fewer requests than the old 2–3 min manual refresh pattern

3

Multi-step modal vs. inline editing — focus over efficiency

Options Considered

A.

Inline row editing in the grid (low friction, familiar pattern)

B.

4-step modal with progressive disclosure — higher-quality configuration

C.

Dedicated full-page configuration form

Why Option B

Inline editing (Option A) was rejected because configuration decisions cascade — report type determines which filters are available. That dependency chain can't be expressed in a flat row edit. Full-page (Option C) adds navigation overhead for what users experience as a quick setup task. Modal keeps context without navigation cost.

Tradeoffs

Modal adds 1 layer of interaction vs. inline — acceptable for the complexity being managed

40% fewer abandoned configurations — partial save API meant returning to a draft was seamless

Step-level validation catches errors earlier — fewer "submitted with wrong date range" corrections

What I explicitly chose not to build — and why

Real-time ETA estimation

Proposed for the progress bar. Rejected: ETA accuracy for variable-sized reports would have been poor — a 30-minute estimate that shows 45 minutes is worse than no estimate. We showed percentage complete only. ETA is on the roadmap once we have enough historical data for reliable ML-based estimation.

In-app report preview before download

Requested by product. Rejected for v1: rendering 10,000-row report previews in-browser would have required significant infrastructure. The use case (verify format before downloading) was better served by a standardized report format guide. Deferred to v2 with PDF preview endpoint.

Report scheduling via natural language

Suggested as a "delight" feature ("run every first Monday"). Rejected: natural language parsing adds ambiguity for compliance-critical scheduling. A structured scheduler (day/week/month with time picker) is less charming but unambiguous — appropriate for regulatory reporting contexts.

Report Lifecycle State Model

The canonical 7-state model that became the platform standard

Before this work, three internal teams used six different terms for the same states. This canonical model — defined through facilitated cross-team workshops — became the single source of truth for all async operations platform-wide. UI copy, API response labels, and support documentation all aligned to these definitions.

This model was adopted for all async platform operations: User ID imports, bulk updates, and export jobs.

Success Path

📨

Submitted

Immediately visible to user

Queued

Position in queue shown

Processing

Real-time % progress

📦

Finalizing

Brief final step

Completed

Push notification sent

Failure Path

Processing

From any active state

Failed

Specific error shown

Queued

Retry returns to queue

🗂

Expired

File deleted per retention policy

Why "Finalizing" as a Separate State?

Operations teams needed to distinguish "generation complete" from "download available." File assembly (packaging, encryption, storage) takes 10–30 seconds. Without Finalizing, users saw Processing → Completed with a blank progress bar and thought the system froze.

Failed State: Actionable Errors

Generic "Report failed" messages were the #1 complaint in exit surveys. Each failure mode now shows a specific reason + one-click remediation action: "Filter returned 0 records — adjust date range" with a direct link to reconfigure.

Expired: Compliance Requirement

SOX and SEC audit requirements meant report metadata must be retained even when files are deleted per retention policy. The Expired state shows metadata and generation date even after the file is gone — audit trail preserved, storage controlled.

Service Blueprint: Report Generation Lifecycle

What the user sees vs. what happens behind the scenes

Layer

1. Configure

2. Submit

3. Processing

4. Complete / Error

User Actions

Opens report creator

Selects type, sets scope and date range, adds optional filters, configures schedule

Clicks "Create Report"

Sees confirmation and is redirected to reports list with new entry visible

Monitors progress

Views live progress bar and % complete. May close page — will receive push notification on completion

Downloads or retries

Downloads file or reads specific error message with remediation action

Front-Stage (UI)

4-Step Modal

Progressive disclosure — only required fields per step. Partial save on each step. Step-level validation.

Confirmation Screen

Toast notification. New row appears in "Submitted" state in AG Grid immediately.

Real-Time Progress Bar

% complete updated via WebSocket every 5s. Status badge transitions in real-time. ETA withheld (accuracy too low).

Status Badge + Action

Completed: download button. Failed: "Retry" or "Edit Configuration" with specific error message.

— — — Line of Visibility (User sees above / System operates below) — — —

Back-Stage (API / Service)

Form Validation API

Validates filter combinations. Checks scope returns results. Returns errors per field for step-level guidance.

Queue Entry API

Duplicate detection: hash of parameters. If identical job already queued, links user to existing entry rather than creating new job.

Worker Processing + WebSocket

Query execution, data aggregation, file generation. Progress broadcast every 5s via WebSocket. Fallback: 30s polling.

File Assembly + Notification

Package output, apply encryption, upload to signed URL. Push notification via WebSocket + optional email for 10+ min reports.

Infrastructure

REST API + partial-save session store

Job Queue (Redis) + duplicate-detection hash store

Worker Pool (horizontal scaling) + WebSocket server

S3 / signed URL storage + notification service + audit log

Design-Engineering integration note: The duplicate-detection hash (Back-Stage, Submit column) was a collaborative solution to the 58% duplicate submission problem. Engineering proposed server-side deduplication. I designed the front-stage experience to match: instead of showing an error, the UI silently links the user to the existing job with a banner reading "A matching report is already in queue — we'll notify you when it's ready." No friction, no confusion.

User Journey: Operations Manager Generating a Monthly Compliance Report (Before)

Operations Manager — Monthly SOX Compliance Report Generation

Persona: Operations Manager — generates 10–15 compliance reports per month, each covering 500+ records

Phase 1

Configure & Submit

Actions

Opens report creation form — 14 fields on single screen

Works through fields without clear priority signal

Submits and receives no confirmation message

Pain Points

×

31% of configurations abandoned at the filter step

×

No clear indication of which fields are required vs. optional

×

Form submission gives no feedback that request was received

neutral

Phase 2

Wait & Wonder

Actions

Navigates away to continue other work

Returns to check status after ~15 minutes

Cannot find the report in the list

Pain Points

×

No progress indicator — no confirmation processing has started

×

Status of "Processing" is ambiguous — how long is normal?

×

"Processing" could mean queued, running, or hung

frustrated

Phase 3

Resubmit (Duplicate)

Actions

Concludes original submission was lost

Re-opens the configuration form

Submits identical report again

Pain Points

×

67% resubmission rate for reports running 30+ minutes

×

Duplicate submission creates two reports in queue

×

Queue congestion slows all reports for all users

frustrated

Phase 4

Eventually Downloads

Actions

Finds one or both versions in "Completed" state

Cannot tell which version is correct

Downloads one and checks manually

Pain Points

×

No timestamp on completion — cannot tell which ran when

×

No metadata about what configuration produced which report

×

Lost trust in system reliability — contacts support regardless

frustrated

Design Process

1

1. State Modeling & Terminology Workshop

Before any UI work, I facilitated a cross-team workshop to define a canonical state model. Engineering, operations, and support were in the room. My role was to translate between technical state machines and user-facing vocabulary — ensuring the final model served both compliance auditing and everyday user comprehension.

Methods

Cross-team workshop facilitation

State diagram exercises

Terminology audit (14 variants catalogued)

Deliverables

Canonical 7-state model

Status glossary with user-facing definitions

State transition rules and trigger conditions

2

2. Research & Behavioral Analysis

Session recording analysis quantified the duplicate submission problem. Exit surveys on abandoned configurations identified the filter-step as the primary drop-off point. Both findings were presented with specific data to secure engineering investment in WebSocket infrastructure and partial-save API.

Methods

Session recording analysis (n=200)

Funnel analysis on configuration flow

Exit survey (n=47 responses)

Deliverables

Behavioral analysis report

Priority matrix for impact vs. effort

Business case for WebSocket investment

3

3. Architecture & API Design Collaboration

Worked with backend engineers to design the duplicate-detection hash, WebSocket progress broadcast frequency, and partial-save API for the multi-step modal. Defined the UX requirements that drove infrastructure decisions — not just accepting technical constraints, but shaping them.

Methods

Architecture sessions with engineering

API contract design

WebSocket frequency optimization testing

Deliverables

Duplicate detection API spec

WebSocket event schema

Partial-save session API design

4

4. Design, Test, and Iterate

Three prototype iterations with operations team members. First round revealed that the Finalizing state needed clearer differentiation from Processing. Second round validated the multi-step modal flow. Third round tested the failure state error messages — specificity was the key variable.

Methods

Prototype testing (3 rounds, 6 participants)

A/B test on error message specificity

Accessibility audit before handoff

Deliverables

High-fidelity prototype

Usability test findings + iteration log

Accessibility audit report

High-Fidelity Design Solutions

AG Grid with Report Type Tabs + Real-Time Progress

Tab navigation organizes Recurring, One-Time, and System-Generated reports into focused views while reusing a single component. Real-time progress bars eliminate the primary driver of duplicate submissions.

after

After: Enhanced Bulk Reporting System

Tab organization + real-time status eliminates uncertainty and duplicate submissions

Bulk Reporting

Generate and manage compliance, operational, and audit reports

Recurring Reports

One-Time Reports

System-Generated

+ Create Report

Export All

⚙ Filters

Search reports...

Report Name

Schedule

Status

Progress

Last Completed

Actions

Monthly SOX Compliance

Monthly — 1st

Processing

65% · ~3 min remaining

Apr 1, 10:34 AM

Weekly Asset Inventory

Weekly — Mon

Completed

Ready to download

Today, 6:00 AM

Quarterly User Activity

Quarterly

Scheduled

Jan 1, 12:00 PM

Daily Transaction Log

Daily — 11 PM

Failed

Filter returned 0 records

Yesterday, 11:02 PM

Showing 4 of 12 recurring reports · 1 failed

← Prev

Page 1 of 3

Next →

Real-Time Progress (Finding #1)

WebSocket % progress eliminates the uncertainty that drove 67% resubmission rate. Users know the system is working.

Actionable Failure States

Specific error message in the table view: "Filter returned 0 records." Retry or reconfigure — no support ticket needed.

Tab Organization

Three report types separated into focused views. Single AG Grid component, different data contexts — no code duplication.

4-Step Configuration Modal

Breaking the 14-field form into 4 focused steps reduced configuration abandonment by 40%. Each step saves partially. Users can return to a draft. Step 3 (filters) is optional with sensible defaults — the primary cause of abandonment.

after

Create Report: Step 1 of 4 — Report Type

Progressive disclosure reduces cognitive load — required decisions first, optional refinements last

Create New Report

1

Report Type

2

Data Scope

3

Filters (Optional)

4

Schedule

Select Report Type

Choose the type of report to generate. This determines available data and filters in the next steps.

Compliance Report

SOX, SEC, and regulatory compliance reporting across accounts and transactions

Asset Inventory

Track and audit asset locations, assignments, and status across facilities

User Activity

Platform engagement, login history, and permission usage by user or group

Maintenance Reports

Work orders, maintenance schedules, and completion status

Draft auto-saved

Cancel

Next: Data Scope

Progressive Disclosure (Finding #3)

Step 1 shows only 4 options. Step 3 (filters) is explicitly labeled "Optional" with defaults applied. The 14-field overwhelm is gone.

Partial Save (API requirement)

Draft auto-saved at each step. Users who exit can return to find their configuration in progress — 40% fewer abandoned configurations.

Enhanced Filter Builder: Before vs. After

Replacing a basic two-field filter panel with a query-builder pattern and saved presets. Power users can surface their most common filter combinations in one click.

before

Before: Basic Filters

Two fields, no presets, minimal usability

Filter Reports

Status

Date Range

mm/dd/yyyy - mm/dd/yyyy

Apply

✕ No presets

✕ No multi-select status filter

✕ No report type filter

✕ No saved filter states

after

After: Enhanced Filter Builder

Presets, multi-select status chips, and saved filters

Advanced Filters

Save as Preset

Quick Filters

Active Reports

Failed Last 7 Days

Scheduled This Week

Status

Processing

Completed

Scheduled

Failed

Queued

Date Range

Report Type

Apply Filters

Clear

Accessibility: Section 508 Compliance

Long-running asynchronous operations create specific accessibility challenges: progress indicators, live status updates, and complex modal flows all required deliberate accessibility work beyond standard compliance.

📡 Live Region for Progress Updates

Real-time progress updates via WebSocket needed to be surfaced to screen readers without overwhelming them.

aria-live="polite" region announces status changes on transition (not every 5s)

Progress percentage announced at 25%, 50%, 75%, and 100% only

"Report Completed: Monthly SOX Compliance report is ready to download" — full context in announcement

Failure: "Report Failed: Monthly SOX Compliance — filter returned 0 records. Retry or edit configuration."

⌥ Multi-Step Modal Keyboard Flow

The 4-step modal required a complete focus management strategy to maintain orientation through step transitions.

Focus moves to step heading on each step transition — users know where they are

Escape closes modal with confirmation if draft is unsaved

Tab order: step indicator → form fields → Cancel → Next (logical reading order)

Back button returns to previous step without losing forward progress

— Status Differentiation Without Color

7 status states risk over-reliance on color. Each state uses color + text label + icon shape for full WCAG 1.4.1 compliance.

Processing: spinner icon + "Processing" text + indigo badge

Completed: checkmark icon + "Completed" text + green badge

Failed: triangle warning icon + "Failed" text + red badge — icon distinguishes from other states without color

Progress bar: percentage text always shown alongside visual bar

📝 Filter Builder Accessibility

The multi-select status filter chips and date range inputs required custom ARIA work for screen reader usability.

Status chips: role="checkbox" with aria-checked — behave like a checkbox group

Date range: start and end inputs explicitly labeled "Date range start" / "Date range end"

Saved preset buttons: aria-pressed to communicate active state

Filter count announced when applied: "3 filters active, 47 reports shown"

Outcomes & Impact

58%

Reduction in duplicate report submissions

First month post-launch

41%

"Where is my report?" support tickets eliminated

Operations self-serve status lookups

85%

Reduction in API polling load

WebSocket push vs. manual page refresh

40%

Fewer abandoned report configurations

Multi-step modal + partial saves

7

Canonical status states adopted platform-wide

All async operations now use the same model

3→1

Teams aligned on shared status vocabulary

From 6 terms to one canonical glossary

Platform-Wide System Impact

Status model as platform standard

The 7-state canonical model was adopted for all async platform operations — User ID bulk imports, data exports, and scheduled jobs. The cross-team terminology alignment eliminated an entire category of support escalation: mismatched vocabulary between what users reported and what engineers saw in logs.

Infrastructure efficiency

The 85% reduction in API polling wasn't just a UX improvement — it materially reduced server load. The duplicate-detection hash (designed collaboratively with engineering) eliminated server-side waste from identical redundant jobs, improving queue throughput for all users.

Reflection

What I would do differently

The ETA estimation decision (showing % complete but not time remaining) was the right call for v1—but I should have designed the data collection infrastructure to enable better estimates in v2. We're now sitting on months of historical job data without a clear schema for training a simple time-estimate model. Thinking further ahead about what data the feature would need to improve would have been worth the extra sprint.

The unexpected lesson: terminology is design

The terminology workshop felt like process overhead when I proposed it. My PM pushed back. But the 41% reduction in "where is my report?" support tickets was substantially caused by vocabulary alignment, not just UI changes. When support and users finally shared the same words for the same states, support calls became shorter, user self-service became possible, and engineering could respond to bug reports without interpretation overhead. Language work is UX work.

How this influenced my approach to system design

This project validated a principle I now apply to all async system design: users in uncertainty act irrationally from the system's perspective but rationally from theirs. A user resubmitting a 30-minute report every 10 minutes isn't impatient — they're responding to an opaque system the only way they can. Before designing any long-running operation interface, I now start with the question: "What does the user need to see to trust the system is working?" The answer almost always shapes the back-end architecture as much as the UI.

Terminology is infrastructure. The 41% reduction in "where is my report?" tickets came as much from vocabulary alignment across 3 teams as from UI changes. When support, engineering, and users finally shared the same words for the same states, confusion collapsed. In platform UX, language standardization is a design deliverable — not a prerequisite someone else handles before your work begins.

Do you have any project ideas you'd want to discuss?

Do you have any project ideas you'd want to discuss?

Do you have any project ideas you'd want to discuss?