Skip to content

ACS Chat to Microsoft Graph: Identity, History and Cutover

ACS Chat retires September 30, 2028. Microsoft Graph chat serves Teams identities only — here is who it cannot serve and how history moves.

Nachi Raman Nachi Raman · · 16 min read
ACS Chat to Microsoft Graph: Identity, History and Cutover
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

Azure Communication Services Chat is fully retired on September 30, 2028, and Microsoft's named alternative is the Microsoft Graph Chat APIs, which require a Teams licence. Before you scope a single line of that migration, answer one question: can every one of your chat participants be represented by a Microsoft Entra identity that Teams will accept?

For a large share of ACS Chat workloads, the answer is no — and Microsoft says so. Its guidance is that Microsoft 365 chat is usually a good choice for conversations among Microsoft 365 users, guests or supported external users, and usually not a direct replacement when the application requires anonymous or application-defined identities, a white-label or fully embedded client independent of Teams, or consumer- or customer-service chat at internet scale. ACS Chat and Teams chat through Graph are described as offerings that are not equivalent.

That is the fork in the road. If your chat serves signed-in employees and partners, this is a migration. If it serves anonymous website visitors, or renders inside your own product under your own brand, or runs at consumer scale, there is no Microsoft destination and you are looking at a third-party provider or a product redesign. This post covers both branches: how to tell which one you are on, and then — for teams on the migration branch — identity mapping, the two permission worlds, history, reconciliation and cutover.

The September 30, 2028 Deadline for ACS Chat

Danger

ACS Chat is in the fully retired bucket, not the breaking-change bucket. Both ACS Chat and ACS Chat for Teams Meeting Interop are removed after September 30, 2028. Being adjacent to Teams does not exempt it. Microsoft maintains chat history according to your storage policies only until that date, and after the retirement date the supporting data and telemetry for retired services is decommissioned.

Date Event
September 2026 Microsoft announces the ACS retirement; ACS Chat listed as fully retired
October 23, 2026 New customers can no longer sign up for the retiring ACS services
September 2026 – September 30, 2028 ACS Chat in maintenance mode: security, compliance and critical reliability updates only, no new features
September 30, 2028 ACS Chat and ACS Chat for Teams Meeting Interop removed; chat history no longer maintained
After September 30, 2028 Supporting data and telemetry for retired services decommissioned

The authoritative timeline lives in Microsoft's retirement and breaking changes guide for Azure Communication Services. The broader picture of what else breaks — calling, PSTN, SMS, the UI Libraries — is covered in the ACS retirement pillar guide.

Info

A note on sources, as of September 2026. Microsoft's detailed ACS Chat to Graph chat migration guide was, at the time of writing, still carrying a banner marking it Microsoft Confidential and staged for internal approval alongside the retirement guide. The broad migration shape it describes is consistent and useful, but it is explicitly unapproved and subject to change. Every firm claim in this post is anchored either on the retirement guide itself or on the long-standing public Microsoft Graph documentation. Re-check the detailed guidance against the current published version before you build against it.

Who Microsoft Graph Chat Does Not Serve

Start here, because this section decides whether the rest of the post applies to you at all.

Microsoft's own fit guidance lists the conditions under which Graph chat is usually not a direct replacement. Read them as disqualifiers:

  • Anonymous or application-defined communication identities. ACS lets your application mint its own users and issue chat-scoped tokens to them. Graph does not. Every participant needs an identity Teams recognises.
  • A white-label or fully embedded chat client independent of Teams. Graph is an API surface over Teams chats. It does not reproduce the ACS Chat client SDK, and existing UI and notification code is not portable.
  • Consumer or customer-service chat at internet scale. The commercial model alone rules this out: Graph chat requires a Teams licence, per participant, under tenant policy.
  • Application-only, ongoing message sending that impersonates users. The application permission that shows up on the messaging API exists for migration, not for routine service-to-user sending.
  • ACS-compatible client events, token issuance, or thread ownership semantics. WebSocket notifications and Event Grid events are replaced by Graph change-notification subscriptions with a different lifecycle.
  • Identical retention, data residency, notification or moderation behaviour. Teams chat is governed by Teams policy and Microsoft Purview, not your Azure resource configuration.

If any of those is a core requirement rather than a nice-to-have, Microsoft's own framing is that you should treat the project as a product redesign rather than an SDK swap — and that you should evaluate other communication providers. Microsoft's migration recommendations table names Infobip as the third-party option on the Chat row.

The Population That Has No Microsoft Path

Be blunt with yourself about the split. Most real ACS Chat deployments are not homogeneous. A typical product has:

  • Internal staff conversations, which map cleanly to Entra identities
  • Partner or contractor conversations, which map if guest access is permitted by tenant policy
  • Customer conversations with signed-up, identified customers, which may or may not map depending on whether those customers exist in your tenant as external users
  • Anonymous or pre-authentication conversations — support widgets, pre-sales chat, kiosk sessions — which do not map at all

Only the last category is a hard stop, but it is frequently the highest-volume category by message count. Count messages per identity class before you choose a target, because that ratio decides whether this is one migration or two.

The honest outcome for many teams is a split destination: staff and partner chat moves to Teams under Graph, customer-facing chat moves to a third-party CPaaS or into the helpdesk platform that already handles those conversations. That is more work than a single migration, but it is less work than discovering the mismatch at cutover.

The Product Model Mismatch, Line by Line

Where the two systems differ is where your engineering effort lands. Microsoft's comparison, condensed:

Area ACS Chat Teams chat via Graph What you rebuild
Identity Application creates generic ACS users, issues chat-scoped tokens Entra and Teams identities, OAuth permissions, tenant policy An approved identity mapping for every active or imported user
Conversation Application-controlled thread and membership Teams one-on-one, group or meeting chat One-on-one chats are unique per user pair; meeting chats differ
Client Your web or mobile client on the ACS SDKs Teams client, Teams app, or a separately validated Graph-based experience UI and notification code is not portable
Ongoing send Participant sends with an ACS token Signed-in user sends with a delegated permission Backend daemons cannot use migration permission for normal messaging
Real-time events Client WebSocket plus server Event Grid Graph change-notification subscriptions Subscription creation, validation, renewal, throttling, missed-event recovery
History ACS thread messages and ACS retention Teams messages governed by Microsoft 365 Import is a separate, privileged workflow
Governance Azure resource configuration Teams policies, Purview, eDiscovery, retention, DLP Compliance and tenant administrators become stakeholders
Rich content Application-defined content and metadata Teams body, hosted content, mentions, reactions, M365 file links Transformation and rehosting of unsupported content

The row that surprises people is the last one. ACS treats message content as your problem — you define the schema, you attach what you like. Graph expects content shaped for the Teams chatMessage resource. Files do not travel as opaque attachments; they are rehosted in an approved Microsoft 365 location and referenced by link. If your chat carried structured application payloads inside messages — order objects, form submissions, rendered cards — those need a documented transformation or an approved exclusion.

Three Target Experiences

Microsoft frames the destination as a choice between three patterns, and picking one early prevents a lot of wasted design.

Continue in Teams. Users read and send in the Teams client. Your application creates or discovers chats and deep-links users into Teams. This is the lowest-risk option because Teams owns the experience, notifications, accessibility and user controls — none of which you now have to build.

Build a Teams app. Your product becomes a tab, bot, message extension or combination. This is the right pattern when you need application-generated conversational interactions: use a bot for those rather than trying to send routine messages with migration permissions.

Retain a custom experience. Possible, but only after a design review. Graph is an API over Teams data; it does not reproduce the ACS client SDK. You independently design sign-in, token acquisition, consent, chat discovery, message rendering, notifications, subscription renewal, retries, accessibility and policy-aware error handling. Teams that assume this is the "just keep our UI" option consistently underestimate it.

Mapping ACS Identities to Microsoft Entra Users

This is the longest-lead workstream and the one that determines what history can move.

Build a controlled mapping — ACS user ID to Entra object ID to target tenant — held outside source control, with a status and a named decision owner per row. A minimal shape:

acs_user_id,entra_object_id,target_tenant_id,status,decision_owner
8:acs:example,00000000-0000-0000-0000-000000000001,1111...,mapped,identity-team
8:acs:former-user,,,archive-only,records-team

Four rules make the difference between a mapping that survives audit and one that does not:

  1. Match on authoritative business identifiers, not display names. Display names collide, change and are user-editable. If your ACS users were created from an internal user ID or email, map on that.
  2. Validate that the target user exists and can participate. An Entra object ID is not sufficient; the account must be enabled, licensed, and permitted by tenant policy to be in the chat type you are targeting.
  3. Never impersonate an unmapped user. The import API requires attributing each message to a user in the same tenant as the authenticated application. There is no supported way to import a message from somebody who does not exist there.
  4. Give every unmappable identity an explicit disposition. Archive-only or excluded, approved by compliance and product owners, recorded in the map. Silence is not a disposition.

The population that fails mapping is predictable: deleted ACS identities, personal Microsoft accounts, former employees, and anonymous or application-defined users. Microsoft's fit checklist asks for an explicit supported disposition for exactly those categories before you begin.

Warning

Unmappable authors are a data-retention decision, not an engineering one. If a conversation contains messages from users you cannot represent in the target tenant, you have three options: archive the whole thread outside Teams and link to it, import only the mappable portion and accept a gap in the record, or exclude it. The first preserves the record, the second breaks it in a way that is invisible later, and the third is only defensible with documented approval. Decide this with your records and compliance owners before extraction, because it changes what you extract.

Two Permission Worlds: Delegated Messaging Versus Migration Import

The single most common architectural mistake in this migration is reaching for the wrong permission model.

Ongoing messaging is delegated. A signed-in user sends a message with a delegated permission — ChatMessage.Send is the typical least-privileged starting point, with Chat.Create for creating a chat and Chat.Read for reading. The message is sent as that user, because that user is actually present.

Historical import is app-only and privileged. The import workflow requires the Teamwork.Migrate.All application permission with administrator consent, and the request must be made in an application context. This is documented in Microsoft's public import messages into Microsoft Teams chats and channels guidance, which is stable and worth reading directly.

These do not substitute for each other. Microsoft's guidance is explicit that the application permission shown on the messaging API is for migration, not for routine service-to-user messaging, and that you should not use Teamwork.Migrate.All for ongoing messaging. A backend daemon that needs to post into a chat on an ongoing basis is a Teams bot, not a migration app.

Three further constraints worth designing around from day one:

  • Least privilege is expected to be reviewed. Security owners approve delegated and application permissions, and tenant administrators approve the app registration, consent, external access, Teams policies and target data location. Build the permission list you will defend, not the one that is convenient.
  • Consent does not override membership or policy. An admin-consented application still cannot put a user into a chat that tenant policy forbids. Guest and external access settings are a separate gate.
  • Secrets belong in a secret store or workload identity. Never in source, never in a browser or mobile client. This is standard, but migration tooling is written fast and under deadline, which is exactly when it slips.

Verify every permission against the current Microsoft Graph permissions reference rather than trusting a table in a blog post — permissions vary by operation and they change. The shape of the target objects is worth reading directly too, in the Microsoft Graph chat resource documentation.

History: Archive-and-Restart or Import

There are two supported strategies, and the right answer is usually different for different cohorts of conversation.

Option 1: Archive and Restart

Export in-scope ACS messages and metadata to an approved archive, validate the archive is complete and access-controlled, create the target chats, post a transition message through an approved user or bot flow, provide a documented path for retrieving legacy history, then make the ACS experience read-only and retire it on the published timeline. The mechanics of getting chat data out of ACS in the first place — and proving the export is complete — are covered in the ACS data export guide.

Choose this when author mapping is incomplete, exact fidelity in Teams is not a requirement, import support does not cover your cloud or chat type, or the organisation simply prefers a clean break.

This option is considerably cheaper and considerably less risky than import, and it is under-chosen. Teams reach for import because "preserving history" sounds non-negotiable. Ask what the actual requirement is. If it is "a compliance officer must be able to retrieve a 2024 conversation on request," an indexed, access-controlled archive satisfies it. If it is "users must scroll back through three years of messages in the Teams client," it does not.

Option 2: Import History Into Teams

Use the Teams message import workflow. Its constraints, from Microsoft's public documentation:

  • App-only Teamwork.Migrate.All with administrator consent.
  • The target chat must be placed into migration mode before importing, via startMigration, and taken out via completeMigration.
  • One application owns each migration session from start through completion. No other application can import into that chat until the owning application completes the migration.
  • Author attribution is required — the from property must attribute the message to a user in the same tenant as the authenticated application.
  • If you set createdDateTime, it must be later than the target chat's own creation time, must not be in the future, and must be unique down to the millisecond within that chat. A duplicate fails with 409 Conflict.
  • Some imported messages may not be visible in the Teams client until migration is completed.

The retirement guide adds an important scope limit: the documented migration steps focus on one-on-one and group chats, and Teams meeting chat and ACS Teams interoperability scenarios require a separate fit assessment. Do not assume meeting chat supports the same history-import workflow.

The Timestamp Collision Problem

The millisecond-uniqueness rule is the constraint that breaks naive import scripts, and it breaks them late — after thousands of successful messages, when two rapid-fire messages in a busy thread land on the same millisecond.

Handle it deliberately:

  1. Sort deterministically by original timestamp, then by source message ID, so the ordering is reproducible across reruns.
  2. Assign unused millisecond values while preserving relative order.
  3. Record both the original and the effective timestamp against the source message.
  4. Include collision counts in reconciliation output.

Treat 409 Conflict as a collision to resolve, never as an idempotent success. A script that swallows 409s will report a clean run and silently drop messages.

An idempotency ledger — one row per source message, carrying source thread ID, source message ID, target chat ID, target message ID, effective timestamp, status, attempt count and last error — is what makes the run restartable and the reconciliation provable. Write it before you write the import loop, not after the first failed run.

Reconciliation, Cutover and Rollback

Reconcile Before You Complete

completeMigration is a controlled checkpoint, not a formality. Before calling it, verify that expected and imported counts match accounting for approved exclusions, that every imported author matches the identity map, that message order is preserved, that samples of HTML, mentions, links, reactions, hosted content and replies render correctly, and that every source message carries a final status — imported, archived, excluded or failed.

The rule worth writing into your runbook: do not complete a chat merely because most messages succeeded.

The Cutover Sequence

The order matters, and it is the same order that works for any read-write system migration:

  1. Announce the transition through approved communications.
  2. Stop creating new ACS threads.
  3. Make ACS Chat read-only, or stop sends.
  4. Record the final source watermark.
  5. Extract and process the final delta.
  6. Import, reconcile, and complete the target chats.
  7. Enable the Teams or Teams-app experience.
  8. Monitor authentication, Graph errors, subscriptions and support signals.
  9. Preserve the source archive and migration ledger for the approved period.
  10. Remove ACS credentials and resources only after the rollback window closes and records owners approve.

Step 3 is the one teams try to skip to avoid user disruption. Skipping it means you are migrating a moving target, and your final delta never converges.

Rollback Has an Expiry Date

Before the ACS retirement, rollback is real: you can return users to ACS while you correct the target migration. After the source is retired, rollback means invoking a continuity plan or reading from your archive. It does not mean deleting Teams messages and restoring ACS, because ACS will not be there.

Define in advance who can declare rollback, what the last safe source-write time is, how target messages created during cutover are handled, how users are notified, and how divergence is reconciled. We have written separately on how to roll back a failed migration after go-live, and the ACS case has one distinguishing feature: the rollback target itself has an expiry date on the calendar.

Every month you delay narrows the rollback window, not just the migration window.

The Testing Nobody Budgets For

Functional tests are the easy part: create chats, add members, send, list, edit, delete, render content types, receive notifications, renew subscriptions.

The tests that actually protect you are the migration-specific ones:

  • Resume safely after process termination mid-run
  • Retry 429, 5xx and network failures without duplicating messages
  • Resolve duplicate-millisecond timestamps deterministically
  • Quarantine unmapped and ineligible authors rather than failing the batch
  • Compare source and target counts and deterministic samples
  • Verify archive retrieval works for excluded content
  • Confirm the post-completion user experience

Plus the governance tests, which have their own approvers: least-privileged permissions and admin consent verified, tenant policy and conditional access exercised, disabled accounts handled, secrets in an approved store, logs redacting tokens and message content, and retention, DLP, eDiscovery, deletion, legal hold and audit validated with the administrators responsible for them.

Performance testing matters more than usual here because throughput is governed by Microsoft Graph throttling rather than your own infrastructure. Honour Retry-After, keep concurrency bounded, test paging over realistic volumes, and confirm the extraction-plus-import cycle actually fits inside the downtime or coexistence window you have agreed. A migration that needs eleven days of running time and has a weekend window is a plan that has not been tested. If the window is genuinely immovable, the zero-downtime migration patterns are the ones to reach for — coexistence rather than a big-bang cutover.

When to Bring In Help

If your ACS Chat deployment is a few hundred internal threads between employees who all already have Teams accounts, do this yourself. The identity map is a spreadsheet, archive-and-restart is a legitimate answer, and a competent engineer will have it done inside a sprint. You do not need a migration partner for that.

The work gets harder along three specific axes, and none of them is the API surface.

Identity resolution at scale. When ACS users were minted by an application rather than provisioned from a directory, the mapping is a reconciliation problem: matching application-generated identifiers against an authoritative directory, handling deletions and duplicates, and producing evidence a security reviewer will accept. That is data work, not Graph work.

History with provable completeness. Import is mechanically fiddly — millisecond uniqueness, single-owner migration sessions, quarantine handling, restartability — but the genuinely hard part is being able to demonstrate afterwards that every source message reached a known final state. Counts that nearly match are worse than useless, because they look like success.

Split destinations. The common real-world shape is that only part of the estate can go to Teams, and the rest has to land somewhere else entirely. Now you are running two migrations against one source with one cutover, and the reconciliation has to span both.

Separate the two decisions cleanly: who owns the chat runtime afterwards — Teams, a Teams app, a CPaaS, or your helpdesk platform — and who preserves the conversation record underneath it. The first is architecture and belongs with your engineering leadership. The second is a data migration with an audit obligation attached.

At ClonePartner we work on the second. Across 1,500+ migrations and 500+ integrations, conversation history is the piece that gets scoped last and blows up first: author attribution, attachments, threading, timestamps and the reconciliation evidence that proves nothing was lost. We are typically brought in when identities do not map cleanly, when history has to land somewhere other than the runtime target, or when a compliance owner needs a reconciliation report rather than a green build.

If your chat is internal and your users are already in Entra, do it in-house. If the identity map is the hard part, or the record has to outlive both systems, scope the data workstream separately and start it now.

Frequently Asked Questions

Is Microsoft Graph a replacement for ACS Chat?
Microsoft describes ACS Chat and Teams chat through Graph as offerings that are not equivalent. Graph is usually a good fit for conversations among Microsoft 365 users, guests and supported external users under Teams governance, and usually not a direct replacement where the application needs anonymous or application-defined identities, a white-label client, or consumer-scale chat.
When does ACS Chat stop working?
ACS Chat, including ACS Chat for Teams Meeting Interop, is fully retired after September 30, 2028. Microsoft states it will maintain chat history according to your storage policies until that date. Separately, from October 23, 2026, new customers cannot sign up for the retiring ACS services at all.
What Graph permission imports historical chat messages?
Historical import runs app-only and requires the Teamwork.Migrate.All application permission with administrator consent. Normal ongoing messaging does not use it — a signed-in user sends with a delegated permission such as ChatMessage.Send. Microsoft's guidance is explicit that migration permission is not for routine service-to-user messaging.
Can I import ACS chat history into a Teams meeting chat?
Treat that as unproven. Microsoft's retirement guide scopes the documented migration steps to one-on-one and group chats, and says Teams meeting chat and ACS Teams interoperability scenarios require a separate fit assessment. Do not assume meeting chat supports the same history-import workflow.
What happens if some ACS users cannot be mapped to Entra identities?
Those messages cannot be imported with correct author attribution, because the import API requires attributing each message to a user in the same tenant as the authenticated application. Unmappable authors need an approved disposition — archive the content outside Teams, or exclude it with compliance sign-off. Do not impersonate an unmapped user.

More from our Blog

How to Roll Back a Failed Migration After Go-Live
From The Migration Trenches

How to Roll Back a Failed Migration After Go-Live

Rollback is harder than the original migration and often impossible after 72 hours. This guide covers triage, three rollback patterns, and platform-specific constraints for reversing a failed SaaS migration.

Nachi Raman Nachi Raman · · 15 min read