Data Flow
This page details the data flow for the primary use case: submitting a dissertation and receiving an automated quote.
Intake Submission Flow
sequenceDiagram
participant Browser
participant NextJS as Next.js Frontend
participant APIGW as API Gateway
participant PresignedURL as getPresignedUrl
participant S3
participant SubmitIntake as submitIntake
participant DynamoDB
participant ProcessSubmission as processSubmission
participant DocAnalyzer as documentAnalyzer
participant QuoteCalc as quoteCalculator
participant Pipedrive as pipedriveClient
participant GetSubmission as getSubmission
Browser->>NextJS: User fills form & selects .docx
NextJS->>APIGW: POST /intake/presigned-url {fileName}
APIGW->>PresignedURL: Invoke
PresignedURL->>S3: Generate presigned PUT URL
S3-->>PresignedURL: {uploadUrl, s3Key}
PresignedURL-->>NextJS: {uploadUrl, s3Key, submissionId}
NextJS->>S3: PUT uploadUrl (direct upload of .docx)
S3-->>NextJS: 200 OK
NextJS->>APIGW: POST /intake/submit {submissionId, name, email, serviceType, s3Key, ...}
APIGW->>SubmitIntake: Invoke
SubmitIntake->>DynamoDB: PutItem (status: "processing")
SubmitIntake->>ProcessSubmission: Lambda.invokeAsync()
SubmitIntake-->>NextJS: {submissionId, status: "processing"}
Note over ProcessSubmission: Async processing begins
ProcessSubmission->>DocAnalyzer: Invoke
DocAnalyzer->>S3: GetObject (download .docx)
DocAnalyzer-->>ProcessSubmission: {textWordCount, refsWordCount, tables, figures, frontMatter}
ProcessSubmission->>QuoteCalc: Invoke
QuoteCalc->>DynamoDB: GetItem (rate schedule from config table)
QuoteCalc-->>ProcessSubmission: {lineItems, subtotal, adminFee, total}
ProcessSubmission->>Pipedrive: Invoke
Pipedrive-->>ProcessSubmission: {dealId, dealUrl}
ProcessSubmission->>DynamoDB: UpdateItem (status: "completed", analysis, quote, dealId)
Note over Browser: Frontend polls for status
loop Poll every 2-3 seconds
NextJS->>APIGW: GET /intake/submission/{submissionId}
APIGW->>GetSubmission: Invoke
GetSubmission->>DynamoDB: GetItem
DynamoDB-->>GetSubmission: Submission record
GetSubmission-->>NextJS: {status, analysis, quote, ...}
end
NextJS->>Browser: Display quote to user
Key Design Decisions
Presigned URL Upload
The browser uploads the document directly to S3 using a presigned URL rather than streaming through API Gateway and Lambda. This avoids the API Gateway payload size limit (10 MB) and the Lambda payload limit (6 MB for synchronous invocation), allowing files up to 50 MB.
Async Processing
The submitIntake function returns immediately after storing the submission and invoking processSubmission asynchronously. This keeps the user-facing API response fast (sub-second) while document analysis and quote calculation may take several seconds.
The processSubmission function is invoked with InvocationType: 'Event', which means Lambda handles the retry logic. If it fails, Lambda retries up to 2 times.
Frontend Polling
The frontend polls GET /intake/submission/{submissionId} every 2-3 seconds until the status changes from "processing" to "completed" or "error". This is simpler than setting up WebSocket connections for a one-time status update.
Submission States
| Status | Description |
|---|---|
processing |
Submission received, async processing underway |
completed |
Analysis done, quote calculated, Pipedrive deal created |
error |
Processing failed (check CloudWatch logs for details) |
Video Consultation Flow
sequenceDiagram
participant Browser
participant NextJS as Next.js Frontend
participant APIGW as API Gateway
participant TokenGen as tokenGenerator
participant LiveKit as LiveKit Server
Browser->>NextJS: Navigate to /room
NextJS->>Browser: Room join form
Browser->>NextJS: Enter name and room name
NextJS->>APIGW: GET /token?room=xyz&participant=John
APIGW->>TokenGen: Invoke
TokenGen-->>NextJS: {token, url, room, participant}
NextJS->>LiveKit: Connect via WSS with JWT token
LiveKit-->>Browser: Real-time audio/video stream
The token generator creates a short-lived JWT with a room grant scoped to the requested room. The browser then connects directly to the LiveKit server over WebSocket.