Future
This document captures work that has been considered and deferred to protect correctness, simplicity, and long-lived invariants. Nothing here is a commitment.
Purpose
The Upload Engine is deliberately conservative. Many ideas are deferred because:
- the current implementation satisfies all production requirements
- premature optimization would compromise the invariants in
invariants.md - migration cost must be justified by concrete need
Current Implementation Gaps
Based on the source code, these are observable areas where the engine is minimal by design:
| Area | Current State | What's Missing |
|---|---|---|
| Retry policy | Linear backoff 1000 * attempt ms (RetryPolicy.ts:73) |
No exponential backoff, no jitter, no adaptive strategies |
| Persistence | sessionStorage only (UploadPersistence.ts) |
No IndexedDB, no cross-tab sync, no crash recovery beyond tab reload |
| Concurrency | Hard constants (MAX_PARALLEL_UPLOADS = 5, PARALLEL_CHUNK_LIMIT = 5) |
No dynamic tuning based on network conditions |
| Observability | Events emitted to Signal bus | No structured metrics, no duration tracking, no retry analytics |
| Cleanup | Engine does not clean up aborted multipart uploads on S3 | Orphaned objects accumulate until backend lifecycle rules run |
| Error granularity | isRetryableError() checks status codes and network errors |
No differentiation between timeout, DNS, TLS, or rate-limit errors |
Deferred Capabilities
1. Backend Cleanup and Reconciliation
Gap: Aborted uploads leave partial multipart objects in S3. The engine calls session.abort() but does not issue AbortMultipartUpload to S3.
Potential approach:
- Add
UploadService.abortMultipartUpload(uploadId)static method - Call in
UploadWorker.run()catch block when abort is detected - Make cleanup best-effort (fire-and-forget)
Constraints:
- Cleanup must never block state transitions
- Cleanup must be safe to fail silently
completedupload objects must never be touched
2. Enhanced Persistence
Gap: sessionStorage is tab-scoped and cleared on tab close. Browser crash = lost in-progress state.
Potential approach:
- Add IndexedDB adapter behind
UploadPersistenceinterface - Swap via
internalFlagsor config, not constructor change - Keep
PersistedUploadStateshape unchanged
Constraints:
- Must not disrupt existing
sessionStoragepersistence - Cross-tab dedup would require distributed lock or leader election
- Persistence format versioning required (see
migrations.md)
3. Adaptive Retry Strategies
Gap: RetryPolicy.ts uses linear backoff (1000 * attempt). No jitter, no exponential curve, no per-endpoint configuration.
Potential approach:
// Future: RetryPolicy could accept strategy
type RetryStrategy = 'linear' | 'exponential' | 'exponential-jitter';
Constraints:
- Default must remain linear for backward compatibility
- Strategy must not depend on domain context (Invariant #12)
- Predictability over throughput (Invariant #19)
4. Structured Observability
Gap: No structured metrics. Upload duration, retry counts, and failure rates are not tracked.
Potential approach:
- Add
UPLOAD_METRICSevent type toUploadEventunion - Emit at completion with
{ duration, retries, chunksUploaded, bytesTransferred } - Keep it observational — never influence engine behavior (Invariant #18)
Constraints:
- Must be additive to event union (no breaking changes)
- Analytics consumers subscribe to Signal bus externally
- Zero performance impact requirement
5. Dynamic Concurrency Tuning
Gap: MAX_PARALLEL_UPLOADS = 5 and PARALLEL_CHUNK_LIMIT = 5 are compile-time constants.
Potential approach:
- Accept via
UploadEngineconfiguration (not per-upload) - Validate bounds at construction time
- Log effective configuration on first upload
Constraints:
- UI must not control concurrency (Invariant #19)
- Changes must not affect in-progress uploads
- Configuration must be immutable after engine construction
6. Multi-Upload Coordination
Gap: Each upload is fully independent. No batch awareness or dependency ordering.
Potential approach:
startBatch(uploads[])returningBatchId- Batch-level events (
BATCH_PROGRESS,BATCH_COMPLETED) - Per-upload behavior unchanged
Constraints:
- Uploads must remain isolated by default — coordination is opt-in
- Batch failure must not cancel successful individual uploads
- Adds significant complexity — requires strong justification
Explicit Non-Goals
The following are not planned and would require architecture review if ever proposed:
| Non-Goal | Rationale |
|---|---|
| UI-driven orchestration | Violates Invariant #1 (single orchestrator) and #2 (UI independence) |
| Synchronous backend cleanup | Cleanup must never block upload state transitions |
| Storage-level deduplication | Not a correctness concern; bucket hygiene is separate |
| Coupling upload success to domain success | Violates Invariant #9 (upload ≠ domain) |
| Server-side upload orchestration | Engine runs in browser; server upload is a different system |
| File preview / thumbnail generation | Domain concern, not infrastructure |
Evolution Rules
Any future work must:
- Preserve all 20 invariants documented in
invariants.md - Be additive by default — no breaking changes to public API
- Include migration plan if persistence format changes (see
migrations.md) - Include tests verifying backward compatibility
- Be justified by concrete production need, not speculative improvement