Correction, 3 October 2026: An earlier version of this article stated that Microsoft had retired Exchange Web Services for Exchange Online as of 1 October 2026. Microsoft is retiring EWS in Exchange Online in phases: the deprecation began on 1 October 2026, with app allow lists required from 10 October and tenants then switched off individually with seven days’ warning, and EWS is fully and permanently disabled from 1 April 2027. The article has been corrected throughout, along with several technical details on JSON batching, delta queries and unified manifest support.
Exchange Web Services is on its way out of Exchange Online. Microsoft began the deprecation on 1 October 2026 and is switching EWS off in phases, ending with full and permanent disablement on 1 April 2027. From 10 October 2026, tenants in the worldwide cloud that keep EWS enabled must maintain an allow list of the applications permitted to use it; tenants that have not set EWS either way are then switched off tenant by tenant, each with seven days’ warning in Message Center, and administrators can turn EWS back on until the final cut-off. After April 2027 there are no exceptions. EWS in on-premises Exchange Server is unaffected.
Some of the bridges that Outlook add-ins quietly relied upon have already gone: Microsoft has turned off the legacy Exchange Online callback and identity tokens across all Microsoft 365 tenants. The rest — makeEwsRequestAsync calls and EWS streaming and pull notifications against Exchange Online mailboxes — go with EWS itself. If your team has completed, or is in the final stages of, its EWS to Microsoft Graph migration, the pressing question is no longer “how do we get off EWS?” It is “once we are Graph-only, what does a well-designed Outlook add-in actually look like?”
This article is about the durable target architecture. Not the mechanics of porting calls one by one, but the patterns that Microsoft Graph Outlook add-in development makes natural — patterns the EWS era made awkward, expensive, or impossible. The goal is to design something that will still be sound in 2027 and beyond: cleanly authenticated, event-driven, throttling-aware, testable, and ready for Copilot and agent extensibility to be layered on without a rewrite.
If you treated the migration purely as a like-for-like swap, you have likely carried forward habits that no longer serve you. The Graph-only world rewards a different shape of system. Here is how we think about it.
Identity and Token Flow: Nested App Authentication and On-Behalf-Of
The single biggest architectural shift is how an add-in proves who the user is and acquires the right to call services on their behalf. Under EWS, many add-ins leaned on Exchange callback tokens and identity tokens issued by the host — a convenient model that Microsoft has now closed for Exchange Online: legacy Exchange Online user identity tokens and callback tokens are no longer supported and are turned off across all Microsoft 365 tenants (they remain supported for Exchange on-premises). The Graph-only replacement is built around modern OAuth 2.0 flows, and getting this layer right is foundational because everything else depends on it.
For new and modernised Outlook add-ins, nested app authentication (NAA) is the approach Microsoft recommends. NAA is provided by the MSAL.js library rather than by Office.js: your add-in, running nested inside the Outlook host, acquires tokens through MSAL on the basis of the user’s existing signed-in session — silently where possible, and through an MSAL pop-up only when interaction is genuinely required, for example to complete multi-factor authentication. Microsoft now describes the older Office.js getAccessToken single sign-on as a legacy pattern, for maintaining existing add-ins or supporting older Outlook clients without NAA, so check for NAA support at runtime and keep a fallback for those clients. The add-in obtains a token for Microsoft Graph, or for your own API, and, critically, the token acquisition logic lives in well-supported library code rather than bespoke plumbing.
NAA also lets an add-in call Microsoft Graph directly from its client code, with no middle-tier server, and Microsoft presents that as one of its benefits. Where your add-in needs to call Graph from a backend service instead — and, as we argue below, we think it usually should — the on-behalf-of (OBO) flow is the Microsoft identity platform pattern that ties the front end to the back end securely. The add-in uses NAA to acquire an access token for your API (a custom scope on your own app registration; Microsoft is explicit that the ID token must never be passed outside the client code that received it), sends it to your backend, and the backend exchanges that token for a Graph token representing the same user. The user’s delegated permissions flow through cleanly; your backend never sees a password, and you never store long-lived user credentials.
Designing this layer well means being deliberate about scopes. Request the least privilege you need — Mail.Read rather than Mail.ReadWrite if you only read, Calendars.Read where calendar write is not required — and document why each scope exists. Admin consent conversations with your customers’ IT teams go far more smoothly when your permission set is minimal and justified. It also means deciding early whether a given operation should run as the signed-in user (delegated) or as the application (application permissions) — for example, a background reconciliation job that runs without a user present needs application permissions and a separate, carefully governed consent path.
The architectural payoff is significant. By centralising identity on NAA and OBO, you decouple the question “who is this user and what may they do?” from the question “what does this feature do?” That separation is exactly what the callback-token era made hard.
Change Notifications Instead of Polling: Webhooks and Subscriptions
The EWS world gave you streaming and pull subscriptions to know when a mailbox changed. Add-ins and companion services that needed to react to new mail or calendar updates either held open streaming connections or polled on a timer. Both approaches were operationally heavy and scaled poorly.
Microsoft Graph replaces this with change notifications — webhooks driven by subscriptions. You create a subscription against a resource, such as /me/messages, /users/{id}/events, or a specific mail folder, and Graph posts a notification to your HTTPS endpoint whenever a matching change occurs. This is a fundamentally better fit for a modern add-in architecture, but it has its own design discipline.
A few patterns are worth building in from the start:
- Validate and renew subscriptions deliberately. Your endpoint must answer Graph’s validation request when a subscription is created, and subscriptions expire: for Outlook messages, events and contacts the maximum lifetime is just under seven days, or under one day if the subscription includes resource data. Your backend needs a renewal job that extends subscriptions before they expire, and it should register for lifecycle notifications, which Graph uses to tell you when a subscription needs reauthorising, when it has been removed and must be recreated, and — for Outlook resources — when notifications have been missed. Treat subscription lifecycle as first-class infrastructure, not an afterthought.
- Acknowledge fast, process asynchronously. Graph treats a notification as delivered when your endpoint returns a
2xxresponse within three seconds, and Microsoft recommends validating the notification, persisting it to a queue and returning202 Acceptedinside that window. Doing real work inline risks timeouts, and if your endpoint does not respond in a timely manner Graph may start dropping notifications, which cannot be recovered. A lightweight queue between the webhook and your processing logic absorbs bursts and isolates failures. - Treat notifications as hints, not payloads. A change notification tells you something changed; for anything beyond trivial cases, fetch the current state from Graph using the resource ID rather than trusting the notification body. Check
clientStateon every notification to confirm it came from Graph, and consider rich notifications with resource data and encryption only where the payload genuinely saves a round trip — for Outlook resources they require$selectand shorten the subscription lifetime to under a day. - Design for delta. For mailbox and calendar synchronisation, pair notifications with Graph delta queries so that when you do reconcile, you pull only what changed since your last sync. Message delta is scoped to a folder (
/me/mailFolders/{id}/messages/delta), so track each folder you care about, store the@odata.deltaLinkGraph returns at the end of each round, and use it to start the next one. This is the natural Graph replacement for EWS-era synchronisation code.
The result is an event-driven backbone: Graph tells you when something happens, your service reacts, and your add-in surface stays responsive because it is not the thing doing the polling. Microsoft’s throttling guidance makes the same point from the other direction: continuously polling a resource, or repeatedly scanning collections for changes, makes an application more likely to be throttled, and Microsoft recommends change tracking and change notifications instead.
Designing for Throughput: JSON Batching and Throttling-Aware Patterns
EWS had its own throttling policies. Graph documents its throttling behaviour and publishes service-specific limits — for Outlook, applied to each combination of app and mailbox — which means you can and should design for it explicitly rather than discovering limits in production.
Two techniques belong in every serious Microsoft Graph Outlook add-in development effort.
JSON batching lets you combine up to twenty individual requests into a single HTTP call to the $batch endpoint. When your add-in needs to read a message, fetch the sender’s profile photo, and check a calendar in one user interaction, batching turns three round trips into one, which cuts network latency. What it does not do is reduce what counts against your limits: Graph evaluates each request in a batch individually against throttling limits. A 200 on the batch also says nothing about whether the requests inside it succeeded, so error handling has to work per sub-request. Be mindful that requests within a batch can run in any order unless you declare dependencies with dependsOn, and that an individual request inside a batch can be throttled even when the batch as a whole succeeds — it comes back with its own 429 and retry-after value, and Graph SDKs that retry throttled requests automatically do not retry those inside a batch. For Outlook, Graph also passes batched requests to the Outlook service at most four at a time, in line with Outlook’s limit of four concurrent requests per app per mailbox.
Throttling-aware design means treating 429 Too Many Requests as an expected condition, not an error to log and forget. When Graph throttles you it returns a Retry-After header; the correct behaviour is to honour it, and Microsoft describes backing off for the Retry-After delay as the fastest way to recover, because Graph keeps logging usage while a client is being throttled. Where Retry-After is absent, Microsoft recommends exponential backoff; where you are also issuing many concurrent requests, we add decorrelated jitter so that retrying clients do not synchronise and hammer the service in lockstep. A retry policy along these lines — respect Retry-After first, otherwise back off with randomised, capped delays, and cap total attempts — keeps your add-in resilient under load and avoids cascading failures.
Crucially, this logic belongs in one place. If retry and batching behaviour is scattered across every Graph call in your add-in’s JavaScript, you will get it subtly wrong somewhere. Centralising it in a shared client — ideally in the backend service discussed next — means you implement it once, test it once, and benefit everywhere.
Lifecycle and Activation: Event-Based Add-Ins and the Unified Manifest
The EWS era’s add-ins were largely defined by buttons that opened task panes. The Graph-only era invites a richer, more integrated lifecycle, and two capabilities are central to designing it well.
Event-based activation lets your add-in run code in response to Outlook events without the user opening a task pane at all. The canonical example is OnMessageSend and OnAppointmentSend handlers that run when a user sends an item — useful for compliance checks, automatic tagging, or recipient validation. Microsoft expects event handlers to be short-running and lightweight: an event-based add-in times out after approximately 300 seconds, and a Smart Alerts send handler that runs for more than five seconds shows the user a dialog saying it is taking longer than expected. That makes the case for keeping the in-client handler thin and delegating substantive work to your backend even stronger. Plan the deployment model too: event-based add-ins activate automatically only when an administrator deploys them — if users install the add-in themselves from Microsoft Marketplace, its event handlers will not launch automatically, though Microsoft documents listing options that work around this. Smart Alerts built on send events are a far cleaner pattern than the client-side hooks teams used to bolt on.
The unified manifest for Microsoft 365 is the other half of the lifecycle story. It is a JSON manifest — an expanded version of the one long used for Teams apps — and it lets an add-in be combined with other Microsoft 365 extensions, such as Teams apps and Copilot agents, into a single app that installs as a unit. It is generally available for Outlook add-ins and, since July 2026, for Word, Excel and PowerPoint add-ins too, and Microsoft recommends it for most scenarios. It has not replaced the add-in only (XML) manifest, which remains valid for production add-ins, and the platform gaps matter for Outlook: unified-manifest add-ins cannot yet be installed in Outlook on Mac, on mobile, or in perpetual versions of Office on Windows, so to reach those users Microsoft’s guidance is to ship a second version of the add-in that uses the add-in only manifest. Even so, our view is that if you are architecting for 2027, designing against the unified manifest now means you are not facing a second migration when you want to add agent capabilities later.
Think of activation as a spectrum: ribbon commands and task panes for rich interaction, event-based handlers for automation at the moment of action, and a manifest that can grow to describe more than just an add-in. Designing for all three from the outset avoids painting yourself into a corner.
Decoupling Add-In Logic into a Backend Service
Almost every recommendation above points in the same direction: get the heavy lifting out of the add-in’s client-side code and into a backend API service that you own. This is the architectural decision that most distinguishes a robust Graph-only add-in from a fragile one.
It was tempting under EWS to keep logic in the add-in, because makeEwsRequestAsync let the task pane call EWS directly. With NAA and OBO there is no such pull towards the client: your add-in can acquire a token for your API, and your API can do the real work. The benefits compound:
- Testability. Business logic in a backend service can be unit and integration tested with proper tooling, mocked Graph responses, and CI pipelines. Logic trapped in an Outlook task pane is far harder to test and almost impossible to test deterministically against the host.
- Reuse across clients. The same backend can serve your Outlook add-in, a Teams app, a web portal, and a future agent. You implement “summarise this thread” or “file this email against a case” once. Without a backend, you reimplement it per surface.
- Secret handling. Client secrets, certificates, and application permissions must never sit in browser-delivered JavaScript. A backend service is the only correct home for them. This alone is sufficient reason for many features to require a backend.
- Centralised resilience. Batching, retry-with-jitter, subscription management, and delta synchronisation all live in one well-tested layer rather than being duplicated across the front end.
- Auditability and governance. A backend gives you a single place to log Graph access, enforce policy, and satisfy the data-handling requirements that enterprise customers increasingly demand.
The add-in becomes a thin, well-behaved presentation layer: it authenticates the user, renders UI, and calls your API. Your API holds the logic and talks to Graph. This is not over-engineering — it is the shape that makes everything else in this article practical to implement and maintain.
Future-Proofing for Copilot and Agent Extensibility
The most strategic reason to design carefully now is that the Microsoft 365 platform is moving towards AI-assisted and agentic experiences, and the architecture described above is precisely the foundation those experiences need. You do not need to build Copilot integration today. You need to avoid decisions that would prevent it tomorrow.
Three design choices keep that door open.
First, the unified manifest is what lets an add-in be packaged with Copilot agents and deployed as a single unit, and it is where an add-in describes how it integrates with Copilot. Microsoft currently labels that integration as preview — its add-in documentation lists custom Copilot agents that read and write documents open in Office applications as a preview capability — so treat it as something to design towards rather than ship on today. An add-in already defined in the unified manifest is, in our view, a short step from describing an agent alongside it.
Second, the backend API service is exactly what agent extensibility wants to call. Declarative agents for Microsoft 365 Copilot are given capabilities — actions, skills, connectors or MCP-based tools — and those map naturally onto the endpoints you have already built and tested. If your logic is locked inside an Outlook task pane, an agent has no clean way to reach it; if it is a clean API, it can be exposed to one.
Third, Microsoft 365 Copilot connectors let you bring line-of-business data from outside Microsoft 365 into Microsoft 365 Copilot, either by indexing it into Microsoft Graph (synced connectors, which use the Microsoft Graph connectors API) or by retrieving it in real time over MCP (federated connectors). If your add-in works with bespoke data — case records, project metadata, line-of-business entities — designing your backend so that the same data can be surfaced through a Copilot connector means your add-in and your future AI experiences share one source of truth rather than diverging.
The pattern is consistent: clean identity, an event-driven backbone, centralised resilient Graph access, and a testable backend are not just good hygiene for an add-in. They are the substrate on which Copilot and agents are built. Architect for them now and the AI layer becomes an addition, not a rebuild.
How McKenna Consultants Can Help
McKenna Consultants has been building software for UK and international organisations since 2004, and Microsoft document integration and Office Add-Ins are core competencies. As an Office add-in development consultancy in the UK, we can help teams move off Exchange Web Services and, just as importantly, design the architecture that comes next. For Workiro, for example, we built an Outlook add-in alongside a Microsoft Graph API server-side integration that lets users tag, import and sync email conversations from Outlook into the Workiro platform.
If your EWS to Microsoft Graph migration is complete or nearly there, we can review your target architecture against the patterns above — identity and OBO flows, change-notification design, throttling resilience, the unified manifest, backend decoupling, and readiness for Copilot and agent extensibility. If it is still in progress, plan against the point at which each customer’s tenant has EWS switched off — Microsoft gives seven days’ warning in Message Center when a tenant is selected — and, at the latest, the final disablement on 1 April 2027. Whether you need an architecture review, hands-on development, or a roadmap that sequences these changes around your release plans, we can help you build an Outlook add-in that is sound for 2027 and beyond.
If you would like to discuss your Microsoft Graph Outlook add-in development, we would be glad to talk through your specific situation. Get in touch with the team to start the conversation.
Sources
- Microsoft Learn — Deprecation of Exchange Web Services in Exchange Online: EWS starts to be disabled in October 2026 and is fully disabled in April 2027.
- Exchange Team Blog — EWS Deprecation Is Here – What This Means To You: the deprecation starting on 1 October 2026, the allow-list requirement from 10 October (worldwide cloud), and the second, tenant-by-tenant phase with a seven-day Message Center warning.
- Exchange Team Blog — Exchange Online EWS, Your Time is Almost Up: unset tenants changed to disabled as the rollout proceeds, re-enabling until final deprecation, full and permanent disablement from 1 April 2027 with no exceptions, and no change to EWS in Exchange Server.
- Exchange Team Blog — Introducing EWSAllowedAppIDs: Preparing for the Final Phase of EWS Retirement: the application allow list.
- Microsoft Learn — Authentication options in Outlook add-ins: legacy Exchange Online identity and callback tokens turned off across all Microsoft 365 tenants, MSAL and NAA recommended, Graph calls from client code without a middle tier, and
getAccessTokenSSO as a legacy pattern. - Microsoft Learn — Enable single sign-on in an Office add-in with nested app authentication: MSAL.js silent and pop-up token acquisition, and the runtime NAA support check and fallback.
- Microsoft Learn — Nested app authentication FAQ: requesting access tokens for your own services with a custom scope, and never passing the ID token outside the client.
- Microsoft Learn — Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow: how a middle-tier API exchanges a user’s token to call a downstream API.
- Microsoft Learn — Set up notifications for changes in resource data: Outlook subscription resources and maximum subscription lifetimes.
- Microsoft Learn — Receive change notifications through webhooks: endpoint validation, the three-second response window,
202 Accepted, dropped notifications andclientState. - Microsoft Learn — Reduce missing change notifications and removed subscriptions: reauthorisation, subscription-removed and missed-notification lifecycle events.
- Microsoft Learn — Set up Microsoft Graph change notifications with resource data: rich notifications for Outlook resources and the
$selectrequirement. - Microsoft Learn — message: delta: folder-scoped message delta queries.
- Microsoft Learn — Combine multiple HTTP requests using JSON batching: the 20-request limit, response ordering,
dependsOnand per-request status codes. - Microsoft Learn — Microsoft Graph throttling guidance:
429andRetry-After, exponential backoff, batched requests evaluated individually, and change tracking in place of polling. - Microsoft Learn — Microsoft Graph service-specific throttling limits: Outlook per-mailbox limits and how batched requests reach the Outlook service.
- Microsoft Learn — Activate add-ins with events: event-based activation, the approximately 300-second timeout, and administrator deployment.
- Microsoft Learn — Handle OnMessageSend and OnAppointmentSend events in your Outlook add-in with Smart Alerts: Smart Alerts and long-running send handlers.
- Microsoft 365 Developer Blog — Unified Manifest Now Available for Office Add-ins: general availability for Word, Excel and PowerPoint add-ins in addition to Outlook.
- Microsoft Learn — Office Add-ins with the unified app manifest for Microsoft 365: platforms that cannot install unified-manifest add-ins, and shipping two versions of the add-in.
- Microsoft Learn — Office Add-ins manifest: the unified manifest as an expanded version of the Teams app manifest, and the add-in only manifest remaining valid for production add-ins.
- Microsoft Learn — Office Add-ins platform overview: the unified manifest recommended for most scenarios, packaging with Copilot agents, and Copilot integration in preview.
- Microsoft Learn — Declarative agents for Microsoft 365 Copilot: agent capabilities, including actions, skills, connectors and MCP-based tools.
- Microsoft Learn — Microsoft 365 Copilot connectors overview: synced connectors indexing external data into Microsoft Graph through the Microsoft Graph connectors API, and federated connectors retrieving it in real time over MCP.
Our client work described here is taken from our published Workiro case study.



