Can a Teams app call channel messages/delta every 5-60 seconds for private and shared channels?

Noah Bates 0 Reputation points
2026-10-14T02:55:38.3566667+00:00

We have a multitenant Teams app that team owners add to their teams. It uses the resource-specific consent permission ChannelMessage.Read.Group.

Change notifications aren't available for private and shared channels with this permission, so for those channels we keep messages in sync by calling GET /teams/{team-id}/channels/{channel-id}/messages/delta with the returned deltaLink.

We'd like to call it every 5 seconds while a channel is active, slowing down to every 60 seconds when it's quiet. That stays well under the published limit of 1 request per second per channel.

Is this usage acceptable for a production app?

Thank you.

Microsoft Teams | Development
Microsoft Teams | Development

Building, integrating, or customizing apps and workflows within Microsoft Teams using developer tools and APIs


2 answers

Sort by: Most helpful
  1. Kai-Ex 1,745 Reputation points Microsoft External Staff Moderator
    2026-10-14T05:27:11.6966667+00:00

    Hi Noah Bates ,

    Please note that this is a user-to-user support forum, and I am not a Microsoft representative. I don't have access to Microsoft's internal systems or guidance to officially confirm whether a specific polling interval is supported for production use. I can only share publicly available information.

    However, I found a related discussion about the limitations of real-time change notifications for shared channel messages. In that discussion, a Microsoft employee suggested using Graph delta queries to check for updates every 60 seconds.

    The discussion also mentions a limit of 60 requests per minute per app per tenant for Teams message APIs, including /messages/delta and /replies, and recommends honoring the Retry-After header and implementing exponential backoff when handling HTTP 429 responses.

    You can find the discussion here: Bot not receiving message events in shared channels (RSC).

    If you need official confirmation on whether this polling interval is supported for production use, you may consider opening a support ticket with Microsoft Support.

    Please note that this is a paid support ticket, which means it requires an active support plan or a one-time support purchase. However, the benefit of using this channel is that your inquiry will be routed directly to the Microsoft Support team responsible for the specific service or feature in question. This team includes engineers and developers who work on the product itself, so they are best positioned to provide accurate, in-depth, and authoritative answers, especially for complex or edge-case scenarios that go beyond publicly available documentation or community knowledge.

    You can refer to this guide Open a new Support request - Microsoft Engage Center | Microsoft Learn

    Was this answer helpful?

    0 comments No comments

  2. AI answer

    2026-10-14T02:56:32.1666667+00:00

    No—calling the channel-messages delta endpoint every 5–60 seconds as a continuous production polling loop does not comply with the documented Microsoft Teams polling requirement, even if every call remains below the 1-request-per-second throttling limit.

    Microsoft states that apps polling to determine whether a Teams resource changed may do so only once per day; apps needing more frequent updates should use change-notification subscriptions. Noncompliant polling can trigger additional throttling or suspension or termination of API access.^1^

    Why the 1-rps limit does not make this acceptable

    The published limits are throttling ceilings, not approved polling intervals. Teams evaluates requests across several independent dimensions, including:

    • Per app across all tenants
    • Per app per tenant
    • Per channel or other resource
    • Per user, when applicable

    The documented default GET limits include 1 rps per chat or channel, 30 rps per app per tenant, and 1,500 rps per app. Specific channel-message GET limits include 1 rps per channel, 20 rps per app per tenant, and 200 rps per app.^2^

    Therefore, a five-second interval might be below the per-channel throttling ceiling but still violate the separate once-per-day polling requirement. A multitenant deployment can also reach aggregate app or app-per-tenant limits before reaching the per-channel limit.

    Supported design for the current RSC model

    For private and shared channels where ChannelMessage.Read.Group cannot provide the required change notifications:

    1. Use the delta endpoint for initial synchronization.
    2. Follow every @odata.nextLink until Graph returns @odata.deltaLink.
    3. Persist the complete @odata.deltaLink unchanged; its state token is opaque.
    4. Use that URL for the next periodic synchronization.
    5. Do not run it as a 5–60-second activity detector. Under the documented Teams polling policy, schedule the check no more frequently than once per day.

    Delta query is a pull-based synchronization mechanism. It reduces transferred data by returning changes since the saved state, but it does not convert polling into a supported real-time event stream.^3^

    A scheduler should therefore resemble:

    async Task SynchronizeChannelAsync(ChannelState state)
    {
        var url = state.DeltaLink ?? state.InitialDeltaUrl;
    
        do
        {
            var page = await graph.GetAsync<DeltaPage>(url);
            await store.ApplyAsync(page.Messages);
    
            url = page.NextLink;
            if (page.DeltaLink is not null)
                await store.SaveDeltaLinkAsync(state.ChannelId, page.DeltaLink);
        }
        while (url is not null);
    }
    

    Also treat 429 Too Many Requests independently from the schedule: honor Retry-After, back off, and avoid immediately retrying rejected requests.

    If low-latency synchronization is mandatory

    The accepted Microsoft Q&A resolution for this exact private/shared-channel RSC scenario states that no additional RSC scope or configuration enables message change notifications there. Its alternative is tenant-wide ChannelMessage.Read.All, which requires tenant-admin consent and the applicable Microsoft Graph protected-API approval process.^4^

    If customers can grant that permission, replace polling with a channel-level subscription to:

    /teams/{team-id}/channels/{channel-id}/messages
    

    Channel subscriptions deliver created and updated messages and replies, can include resource data, and support application-only ChannelMessage.Read.All.^5^

    If tenant-wide permission and admin consent are not acceptable, there is no documented production-supported path in these sources for 5–60-second synchronization of private/shared-channel messages using only ChannelMessage.Read.Group. The practical choices are daily delta synchronization or reduced functionality for those channel types.


    References

    1. Use the Microsoft Graph API to work with Microsoft Teams
    2. Microsoft Graph service-specific throttling limits
    3. Use delta query to track changes in Microsoft Graph data
    4. Teams Bot: Receiving all messages from Private Channels using RSC permissions - Microsoft Q&A
    5. Get change notifications for messages in Teams channels and chats using Microsoft Graph
    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.