# MRT-M07: Mobile performance budget document
**Area:** Mobile-Responsive Testing
**Model:** minimax/minimax-m2.5
**Tokens:** 3,844
**Cost:** $0.0038
**Time:** 2160ms
**Timestamp:** 2026-02-16T12:17:08.467159

---

# Mobile Performance Budget

## Sunaiva Talking Widget

**Document Version:** 1.0  
**Status:** Production-Ready  
**Last Updated:** January 2025

---

## 1. Executive Summary

This document establishes the performance budget for the Sunaiva Talking Widget — an AI voice interface designed for integration into Australian tradie business websites. The budget defines hard limits across five critical metrics to ensure the widget delivers fast, efficient, and battery-conscious performance on mobile devices.

**Budget at a Glance:**

| Metric | Target | Threshold | Hard Limit |
|--------|--------|-----------|------------|
| JS Bundle Size (gzipped) | <40KB | 45KB | 50KB |
| Time to Interactive (4G) | <2.5s | 2.75s | 3.0s |
| Memory Usage (peak) | <80MB | 100MB | 120MB |
| CPU Usage (idle) | <2% | 3% | 5% |
| Battery Drain | <1%/hour | 1.5%/hour | 2%/hour |

All hard limits represent absolute ceilings. Exceeding any hard limit blocks deployment.

---

## 2. JS Bundle Budget

### 2.1 Target

**≤50KB gzipped** (target: ≤40KB)

### 2.2 Rationale

50KB gzipped represents the practical ceiling for a non-critical, embeddable widget. Google Lighthouse penalises scripts exceeding 100KB, and research from the HTTP Archive indicates that widgets exceeding this threshold correlate with measurable conversion drops on mobile.

For a voice widget, we must include:

- Core widget shell
- WebRTC / audio capture abstraction
- Speech recognition interface (Web Speech API or fallback)
- Audio playback engine
- State management
- UI components

Achieving ≤50KB requires aggressive code splitting, tree shaking, and deferral of non-critical functionality.

### 2.3 Bundle Allocation

| Chunk | Target Size (gzip) | Priority |
|-------|-------------------|----------|
| Core widget shell | 12KB | Critical |
| Audio engine | 10KB | Critical |
| Speech recognition wrapper | 8KB | Critical |
| UI components | 6KB | Deferred (<2s TTI) |
| Analytics / telemetry | 3KB | Deferred (<5s TTI) |
| Fallback fonts / assets | 5KB | Lazy load |
| **Total** | **44KB** | — |

### 2.4 Enforcement

- **Build step:** Webpack/Rollup configuration enforces gzip size limit with `maxSize: 50000` (uncompressed ~150KB pre-gzip)
- **CI pipeline:** Bundle size regression >5KB triggers build failure
- **Runtime:** Embedded widget reports actual bundle size to telemetry; >45KB triggers alert

### 2.5 Strategies

- Use dynamic imports for non-critical chunks
- Inline critical CSS; defer rest
- Prefer native Web APIs over libraries (Web Speech API, AudioContext)
- Compress with Brotli (primary) and gzip (fallback)
- Exclude unused polyfills via `browserslist` targeting modern mobile browsers (Safari 14+, Chrome 90+, Samsung Internet 15+)

---

## 3. Time to Interactive Budget

### 3.1 Target

**≤3.0 seconds on 4G** (target: ≤2.5s)

### 3.2 Network Assumptions

Based on Australian mobile network characteristics (Ookla Speedtest data, 2024):

| Network | Download | Upload | Latency |
|---------|----------|--------|---------|
| 4G (typical) | 25Mbps | 8Mbps | 40ms |
| 4G (poor coverage) | 5Mbps | 1Mbps | 80ms |
| 3G (fallback) | 1.5Mbps | 0.5Mbps | 150ms |

The budget assumes **typical 4G conditions**. The widget must degrade gracefully on slower connections but must never exceed 3.0s TTI on 4G.

### 3.3 Budget Breakdown

Total budget: 3000ms

| Phase | Allocation | Rationale |
|-------|-----------|-----------|
| DNS + TCP + TLS | 400ms | Single external domain; preconnect enabled |
| Time to First Byte (TTFB) | 300ms | Edge-hosted widget assets; Australia CDN |
| Content Download | 800ms | 44KB @ 25Mbps = ~14ms; budget includes overhead |
| Parse + Compile | 600ms | Minimal JS; no framework runtime |
| Execution + Init | 900ms | Audio engine init, speech API setup |

**Total: 3000ms**

### 3.4 Critical Path Requirements

1. **Preconnect:** `<link rel="preconnect" href="https://cdn.sunaiva.com">` in host page head
2. **Inline critical CSS:** First paint <500ms
3. **Async/defer script:** `<script defer>` to prevent render blocking
4. **HTTP/2 push:** Use server push for critical chunks (if supported by CDN)
5. **Service worker:** Cache widget assets after first load; subsequent loads <1s TTI

### 3.5 Enforcement

- **Lighthouse CI:** TTI <3.0s required; warning at >2.75s
- **Real user monitoring:** P90 TTI from Australian mobile IPs must be <3.0s
- **Synthetic testing:** WebPageTest on throttled 4G (1.6Mbps, 150ms RTT) as baseline

---

## 4. Memory Budget

### 4.1 Target

**Peak ≤120MB** (target: ≤80MB, threshold: ≤100MB)

### 4.2 Rationale

Mobile devices typically have 2–6GB RAM. However, background tabs, browser chrome, and the host page consume significant memory. A widget exceeding 120MB risks:

- Tab eviction on memory-constrained devices (iPhone 6s, older Android)
- Triggering browser memory warnings
- Degrading host page performance

The 80MB target accounts for typical mobile browser overhead (~30MB) while leaving headroom for the host page.

### 4.3 Allocation

| Component | Typical | Peak |
|-----------|---------|------|
| JS heap (code + data) | 15MB | 25MB |
| DOM nodes (floating button + panel) | 5MB | 10MB |
| Audio buffer (Web Audio API) | 8MB | 20MB |
| Speech recognition buffer | 5MB | 15MB |
| WebRTC buffers | 2MB | 10MB |
| Cached assets / strings | 10MB | 15MB |
| Browser overhead | 25MB | 25MB |
| **Total** | **70MB** | **120MB** |

### 4.4 Enforcement

- **Chrome DevTools Memory Profiler:** Manual profiling on Moto G4, iPhone 8 (physical devices)
- **CI:** `playwright` memory snapshot on page load + 10s idle; hard fail >100MB
- **Runtime:** `performance.memory` (Chrome) or custom telemetry; alert >80MB
- **Cleanup:** Explicit `null` disposal of audio contexts after 60s inactivity

### 4.5 Strategies

- Use `AudioContext` with `close()` on idle; recreate on demand
- Limit speech recognition result buffer to last 30 seconds
- Release DOM references on widget collapse
- Avoid memory leaks: no lingering event listeners, clear timeouts/intervals

---

## 5. CPU Usage Budget

### 5.1 Target

**Idle: ≤5%** (target: ≤2%, threshold: ≤3%)

### 5.2 Rationale

The widget must not measurably impact device responsiveness when idle (user not interacting, no active call). Sustained CPU usage >5% causes:

- Device heating
- Battery drain (covered separately)
- Host page jank (scroll/frame drops)

Voice widgets are inherently more CPU-intensive than static widgets due to audio processing. We must balance responsiveness with efficiency.

### 5.3 States and Budgets

| State | CPU Usage | Description |
|-------|-----------|-------------|
| Dormant | <1% | Widget collapsed, no audio processing |
| Listening (passive) | <3% | Awaiting wake word / activation |
| Processing | <15% | Active speech-to-text, short bursts |
| Playing response | <10% | Audio playback via Web Audio API |
| Peak (transcription) | <25% | Brief spike during intensive processing |

### 5.4 Enforcement

- **DevTools Performance:** Profile 30s idle period; average CPU <3%
- **CI:** `playwright` CPU monitoring via Chrome DevTools Protocol; average >5% fails
- **Runtime:** `navigator.hardwareConcurrency` and `performance.now()` sampling; alert if sustained >3%

### 5.5 Strategies

- Use `requestAnimationFrame` for UI updates; avoid polling
- Leverage Web Workers for audio processing (if needed); keep main thread free
- Pause speech recognition when tab is hidden (`visibilitychange` event)
- Use hardware-accelerated audio codecs via Web Audio API (opus)
- Throttle non-critical telemetry to batched intervals (every 30s)

---

## 6. Battery Impact Budget

### 6.1 Target

**≤2% per hour** (target: ≤1%/hour, threshold: ≤1.5%/hour)

### 6.2 Rationale

Tradie users are often on job sites with limited charging access. A widget that noticeably drains battery damages trust and brand perception. The target of 1%/hour represents an imperceptible impact — roughly equivalent to an idle tab with occasional network activity.

### 6.3 Battery Drain Breakdown

| Activity | Drain (per hour, if continuous) |
|----------|--------------------------------|
| Dormant (no processing) | 0.2%/hr |
| Passive listening (WebRTC active) | 0.8%/hr |
| Active speech-to-text | 2.5%/hr |
| Audio playback | 1.5%/hr |

**Assumption:** Widget is in dormant or passive listening state for 95% of the time. Active states are brief (<30s per interaction).

### 6.4 Calculation

```
Weighted average = (0.95 × 0.2%) + (0.04 × 0.8%) + (0.01 × 2.5%)
                 = 0.19% + 0.032% + 0.025%
                 = 0.247% per hour
```

This assumes:

- Average 2 interactions per hour
- Each interaction: 10s listening + 10s playback
- Remainder: dormant

### 6.5 Enforcement

- **Synthetic:** Manual drain test on iPhone 12 / Samsung S20 — widget in background tab for 1 hour; measure battery %
- **Real-world:** Aggregate battery drain from `navigator.getBattery()` (Chrome only) or estimate from CPU/network activity
- **Alert:** If average CPU >3% sustained, flag for battery impact review

### 6.6 Strategies

- Aggressive idle state: fully suspend audio context after 30s of inactivity
- Use VAD (Voice Activity Detection) to stop listening when user stops speaking
- Batch network requests; avoid persistent connections
- Disable analytics/telemetry when battery <20%
- Use `navigator.connection.saveData` preference to reduce data/cpu when user has enabled data saver

---

## 7. Measurement & Monitoring

### 7.1 Synthetic Monitoring (CI/CD)

| Metric | Tool | Threshold | Action |
|--------|------|-----------|--------|
| Bundle size | webpack-bundle-analyzer | >45KB | Warn; >50KB block |
| TTI | Lighthouse CI | >2.75s warn, >3.0s fail | Block |
| Memory | Playwright + CDP | >100MB | Warn; >120MB block |
| CPU (idle) | Playwright + CDP | >3% avg | Warn; >5% block |
| Parse time | Chrome DevTools Timeline | >500ms | Warn |

### 7.2 Real User Monitoring (Production)

Embed lightweight telemetry (optional; user-consented):

```javascript
const telemetry = {
  tti: performance.timing.loadEventEnd - performance.timing.navigationStart,
  memory: performance.memory?.usedJSHeapSize,
  cpu: /* sampled via requestAnimationFrame */,
  network: navigator.connection?.effectiveType
};
```

- Sample 1% of sessions to minimise overhead
- Send via `navigator.sendBeacon()` to avoid blocking unload

### 7.3 Alerting

| Condition | Severity | Action |
|-----------|----------|--------|
| P90 TTI >3.0s (AU mobile) | High | Page + engineer on-call |
| P90 memory >100MB | Medium | Create Jira ticket |
| CPU >5% sustained | High | Page + engineer on-call |
| Battery drain complaint rate >0.1% | Medium | Product review |

---

## 8. Enforcement & Governance

### 8.1 Process

1. **Development:** Developer runs local Lighthouse + bundle analysis before commit
2. **Pull Request:** CI runs full synthetic test suite; block on any hard limit breach
3. **Staging:** RUM telemetry validates performance on real devices
4. **Production:** Alerts fire if metrics degrade; rollback if P90 exceeds hard limit

### 8.2 Exceptions

Hard limits may be exceeded only with:

- Written approval from VP Engineering
- Documented risk assessment
- Timeboxed remediation plan (max 2 sprints)

### 8.3 Ownership

| Metric | Owner |
|--------|-------|
| Bundle size | Frontend Engineer |
| TTI | Frontend Engineer + DevOps |
| Memory | Frontend Engineer |
| CPU | Frontend Engineer |
| Battery | Product Engineer |

---

## 9. Appendix

### A. Test Devices

Minimum test matrix for mobile performance validation:

| Device | OS | Browser | Network |
|--------|-----|---------|---------|
| iPhone 12 | iOS 16 | Safari | 4G |
| iPhone 8 | iOS 15 | Safari | 4G |
| Samsung S21 | Android 13 | Chrome | 4G |
| Moto G4 | Android 10 | Chrome | 4G |
| iPad Pro | iPadOS 16 | Safari | WiFi |

### B. References

- Google Web Fundamentals: Performance Budgets
- Chrome DevTools Performance Profiler
- Web Audio API Specification
- Web Speech API Specification
- HTTP Archive: JavaScript Bundle Size Trends
- Australian Communications and Media Authority: Mobile Broadband Performance Report 2024

### C. Revision History

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0 | Jan 2025 | Performance Team | Initial production budget |

---

**End of Document**