What the customer experiences
A customer connects a Microsoft 365 tenant, which is the account boundary for their organization, and chooses a folder in their Vimeo video library. After an allowed person finishes a Teams meeting, the recording appears in that folder. Nobody has to download the file, wait for it, and upload it again.
That is also how Vimeo describes the public product: Teams recordings are sent to a designated folder after the meeting ends. This case study follows the story behind that quiet hand-off: Microsoft announces that a recording exists, the integration discovers and transfers it, and Vimeo places it where the customer asked.
Why the hand-off is difficult
Microsoft Graph is Microsoft's programmatic interface, or API, for Microsoft 365. It does not send a video file when a meeting ends. It sends a small HTTP message called a change notification when a recording becomes available. The standing request for those messages is called a subscription. Subscriptions expire, notifications may contain encrypted recording details, and the video file may still need time before it can be fetched.
The system therefore has to keep three promises at once:
- maintain the tenant's authorization, or granted permission, and subscription over time;
- accept a notification quickly, even when the recording is not ready;
- place one recording in one Vimeo destination when delivery is retried.
The dangerous failures are quiet. An expired subscription produces no event. An unmapped user gives the system no safe destination. A duplicate notification looks valid unless the recording has a stable identity throughout the flow.
Four ideas used in the rest of the story
Webhook
An HTTP request sent by Microsoft Graph to announce a change. It is a notification, not the recording file itself.
Kafka
A durable event log used for the hand-off. It stores accepted work so a recording can wait for a worker without keeping the webhook request open.
Consumer and offset
A consumer is a worker that reads Kafka records. Its offset is the saved position that says how far it has completed.
Idempotency
Repeating the same logical recording operation converges on the same archive result instead of creating another video.
My role
I led the technical work on Vimeo's integrations team. I took the product requirements into design discussions, wrote the technical design, broke the work into deliverable pieces, implemented it with the team, and stayed responsible through onboarding and production support.
What I owned on this integration
Define the contract
Worked with product and partner teams to turn ‘archive Teams recordings’ into explicit consent, mapping, folder, and failure behavior.
Design the lifecycle
Specified subscription renewal, notification intake, recording readiness, identity mapping, and retry boundaries.
Build and release
Implemented the integration with the team, drove technical decisions, and supported customer onboarding.
Operate it
Handled production issues, monitoring, and the reliability work that followed real failures.
Follow one recording
How to read the diagrams
- Microsoft Graph, the customer's tenant, and external identities
- The integration boundary, validation, and recording identity
- Durable or recoverable progress, including Kafka and its consumers
- The external recording file and Vimeo upload path
- A condition that must stop or delay the run
From recording notification to Vimeo folder
- recording readyMicrosoft Graph → Webhook receiver
Change notification
subscription proof · encrypted recording details
- intakeWebhook receiver
Validate and decrypt
reject an invalid client state or payload
- before HTTP successWebhook receiver → Kafka
Publish the recording event
keyed by the recording identity
- after the responseKafka → Recording worker
Deliver to a worker
the same record may be delivered again
- if neededRecording worker
Wait and retry until the file is available
not-ready is expected, not data loss
- resolvedRecording worker → Vimeo library
Transfer and place recording
mapped Vimeo account and chosen folder
- durable resultRecording worker → Kafka
Commit the consumed offset
only after the outcome is stored
The subscription request makes the tenant boundary concrete. Microsoft
documents communications/onlineMeetings/ for tenant-wide
recording notifications. It requires the application permission
OnlineMeetingRecording.Read.All, supports encrypted resource data, and needs
a lifecycle notification URL when the requested lifetime exceeds one hour.
In the public request below, clientState is a secret proof that Graph returns
with notifications, the certificate lets the receiver decrypt protected
recording details, and the lifecycle URL receives warnings about subscription
health.
POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json
{
"changeType": "created",
"resource": "communications/onlineMeetings/getAllRecordings",
"notificationUrl": "https://example.invalid/graph/notifications",
"lifecycleNotificationUrl": "https://example.invalid/graph/lifecycle",
"includeResourceData": true,
"encryptionCertificate": "<public certificate>",
"encryptionCertificateId": "<certificate id>",
"expirationDateTime": "<next renewal time>",
"clientState": "<subscription secret>"
}The first reliability boundary is intentionally small: validate the notification, hand the recording identity to Kafka, and return success after Kafka accepts it. Fetching and transferring a video can take much longer than a webhook sender will wait. Kafka absorbs bursts and lets consumers retry without keeping the webhook request open.
What Kafka guaranteed here
Kafka made the hand-off durable and replayable. It did not guarantee one and only one Vimeo upload. Kafka and Vimeo do not share one all-or-nothing operation, so the consumer still needs saved state around the recording.
Reconciliation means checking the saved recording state and any result already returned by the outside system before deciding whether another upload is safe.
- boundary
- Microsoft Graph → intake
- delivery behavior
- The request can be retried
- rule that prevents loss or duplication
- Return success only after the recording event is accepted by Kafka.
- boundary
- Kafka → recording consumer
- delivery behavior
- At least once
- rule that prevents loss or duplication
- Use the recording identity as the idempotency key and commit the offset after the durable outcome.
- boundary
- Consumer → Vimeo
- delivery behavior
- An API timeout can hide whether the upload succeeded
- rule that prevents loss or duplication
- Check stored state and reconcile an uncertain result before creating another video.
- boundary
- Retry path
- delivery behavior
- Temporary failures can produce another attempt
- rule that prevents loss or duplication
- Every attempt resumes the same recording operation rather than starting a new one.
Idempotency here means that processing the same recording event twice converges on one archive result. It does not mean Kafka suppresses duplicates. The consumer earns that property by using a stable recording key, recording progress, and checking the existing outcome before repeating an outside action such as an upload.
Two authorization decisions
This integration needed both organization-level permission and a person-level mapping. They answer different questions.
- layer
- tenant consent
- question it answers
- May this integration read recordings for this Microsoft tenant?
- what it enables
- Application access and recording subscriptions
- failure the customer sees
- The tenant cannot be connected or renewed
- layer
- user connection
- question it answers
- Which Microsoft identity belongs to which Vimeo user?
- what it enables
- Folder choice and safe library placement
- failure the customer sees
- The recording needs mapping before it can be placed
Treating these as one generic “connected” flag would hide useful states. A tenant can be authorized while a particular organizer is still unmapped. A user can have a mapping while the tenant grant has expired. The product needs to say which action is required, rather than showing a vague connection error.
The subscription has its own lifecycle
Graph validates the notification endpoint when a subscription is created.
Subscriptions expire and need renewal. Notifications with resource data use
the certificate supplied at creation, while clientState lets the receiver
reject a notification that does not belong to the subscription.
One recording subscription over time
Create subscription
resource · clientState · encryption certificate
Send validation token
Echo token as plain text
Send recording notifications
resource data may be encrypted
Renew subscription
Reliability means making missing progress visible
- condition
- Publishing to Kafka fails
- system response
- Do not acknowledge the webhook
- why
- Microsoft Graph can retry; returning success here would lose the recording event.
- condition
- Graph retries after Kafka accepted the event
- system response
- Reuse the recording's stable key
- why
- The second event converges on the existing archive attempt.
- condition
- A consumer crashes before committing its offset
- system response
- Kafka delivers the record again
- why
- The consumer checks durable recording state before repeating the upload.
- condition
- The recording is not ready
- system response
- Retry later, waiting longer between attempts
- why
- Availability lag is a normal Microsoft recording state.
- condition
- Consent or stored access is revoked
- system response
- Stop retrying and ask for reconnection
- why
- Waiting and retrying cannot repair missing permission.
- condition
- The organizer has no Vimeo mapping
- system response
- Hold for resolution
- why
- Guessing a destination can expose a recording to the wrong account.
- condition
- A subscription approaches expiry
- system response
- Renew and alert on missing progress
- why
- No incoming error will announce a silent lapse.
The operational lesson was to monitor expected progress as well as explicit errors. Subscription renewal, event age, unresolved mappings, and recordings stuck before placement each reveal a different break in the customer promise.