Power Automate to sync Google Calendar with Outlook: the flow limits
Power Automate can move events between Google Calendar and Outlook. That part is settled, and the flows are not hard to build. The question worth answering before building one is what the result will be like to live with, because a two-way calendar sync built on polling connectors behaves differently from the sync a calendar app performs natively, and the differences show up in specific, predictable places.
Microsoft publishes the connector reference for both sides, which means the limits are not a matter of opinion. The throttling numbers, the trigger intervals, and the exact list of fields each action can read and write are documented. Reading them first tells you which parts of a calendar will cross intact and which will quietly fail to.
What the two connectors actually offer
The Google Calendar connector is published by Microsoft, classed as Standard, and available across Power Automate, Logic Apps, Power Apps, and Copilot Studio in all regions except the China Cloud operated by 21Vianet.
Its action list is short. Create an event, Delete an event, Get an event, List calendars, List the events on a calendar, Update an event. Six actions, and that is the whole surface.
The triggers are five: when an event is added to a calendar, when an event is updated, when an event is deleted, a combined trigger for added or updated or deleted, and when an event starts. The combined trigger is the one most sync flows use, because it returns an action type field telling you which of the three happened.
On the Outlook side the Office 365 Outlook connector is considerably larger, and its calendar operations are versioned. Create event is on V4, Get events on V4, Get calendars on V2, and the added or updated or deleted trigger is on V3. The earlier versions are still listed and marked deprecated, which matters when you copy a flow from a blog post written three years ago: the action it names may still exist and still be the wrong one to build on.
The numbers that set the ceiling
Both connector pages publish throttling limits, and they are not the same.
| Google Calendar connector | Office 365 Outlook connector | |
|---|---|---|
| API calls per connection | 100 per 60 seconds | 300 per 60 seconds |
| Frequency of trigger polls | 1 per 90 seconds | Not published on the connector page |
The Google side is the binding constraint in almost every design. One hundred calls per minute sounds generous until you count what a single sync pass costs. A flow that lists events, reads each one to compare it, and writes the changed ones spends several calls per event. Backfilling a year of history, or recovering after the flow was switched off for a week, is exactly the situation where a loop hits the ceiling and starts failing partway through.
The trigger poll limit is the one that shapes user experience. One poll per ninety seconds is the floor, so ninety seconds is the best case for how long a new Google event takes to reach the flow. In practice the interval you configure is longer, and the Office 365 documentation adds its own caveat: triggers fire almost immediately in most cases, but in rare circumstances the delay can reach one hour.
Plan around that honestly. A sync built this way is not for a schedule that changes while you are looking at it. It is for keeping two calendars roughly aligned over the course of a day.
Polling is not a change feed
The deeper issue with the Google connector is how it reads. The List the events on a calendar action is documented as returning the first page of arbitrarily ordered events on the selected calendar. Not the most recent, not the changed ones. The first page, in no defined order.
That single sentence rules out several designs that look obvious. You cannot page through a calendar deterministically, you cannot ask for everything modified since a timestamp, and you cannot rely on the order to know where you stopped. The action does accept a minimum time, a maximum time, and a text search query, so the workable pattern is to bound every read by a date window and accept that events outside that window are invisible to the flow.
This is why most working implementations sync a rolling window rather than a whole calendar. Something like thirty days back and ninety days forward, re-read on each pass. History further back than the window stays wherever it already is, and nobody notices until the day they need a meeting from eighteen months ago.
The fields that do not survive the crossing
The Google connector's event definition lists exactly what it returns: title, start, end, description, location, status, HTML link, event ID, attendees, creator, organizer. The create and update actions accept title, start, end, description, location, attendees as a comma-separated list, status as confirmed or tentative or cancelled, and an all-day flag.
Read that list for what is absent rather than what is present.
There is no recurrence field. No reminder or alert settings. No time zone on the event itself, only the start and end date-time values. No conferencing data, so a Google Meet link exists only if it happens to appear in the description text. No free-or-busy marker, so an event marked as available in Google arrives in Outlook as ordinary busy time. No colour and no visibility setting, so a private event does not stay private by virtue of the sync.
Each absence is a decision the flow has to make on your behalf. The usual compromise is to treat the synced copy as a placeholder: correct title, correct time, correct location, and nothing else. That is genuinely useful for availability, and it is why the copies should live on their own calendar rather than mixed into the working one. Someone looking at a synced placeholder needs to know not to trust its reminders.
Attendees deserve a specific warning. The field accepts a comma-separated list of email addresses, which means a flow that copies attendees is issuing real invitations from the destination calendar. Guests get a second invitation to a meeting they already accepted, from an organizer who is not the person running the meeting. Most designs that survive contact with colleagues drop attendees entirely and put the guest list in the description instead.
The echo problem
A one-way flow is straightforward. A two-way flow has a structural problem: the event it writes into Outlook triggers the Outlook-side flow, which writes back to Google, which triggers the Google-side flow. Left alone, a single meeting multiplies.
There is no built-in suppression for this, so the flow has to recognise its own output. Two markers are commonly used, and both work.
The first is a text marker in the description or body, something like a bracketed tag the flow writes on every event it creates. Each flow checks for the tag at the start and terminates if it finds one. Simple, visible, and it survives the connector's field list because description is one of the fields that does cross.
The second is an identity table. The flow stores a row pairing the Google event ID with the Outlook event ID, and consults it before writing. This is more work and considerably better, because it also solves updates and deletions: without a stored pairing, the flow has no way to know that the event it is looking at is the same meeting it copied last week, and the usual symptom is duplicates appearing after every title change.
Timestamps help less than expected. The Google connector's event definition returns no modified time and no etag, so there is no field to compare that says which copy is newer. A two-way flow therefore cannot resolve a genuine conflict, the case where the same meeting was edited on both sides between passes. The only workable policies are to declare one side authoritative and let it overwrite, or to stop on conflict and raise it for a person to settle. Choosing neither means the last flow to run wins, which is effectively random.
Deletion is the case that catches people out. The Google delete trigger tells you an event was removed, and the payload carries the event ID. Without a stored mapping, that ID means nothing on the Outlook side, so the copy stays. A calendar that accumulates cancelled meetings is worse than no sync at all.
Recurring events are the hardest part
The combined Google trigger takes a parameter named Expand Recurring Events, which controls whether a repeating series arrives as a series or as individual instances. Neither setting is comfortable.
Expanded, a weekly meeting arrives as a long run of separate events, each one consuming calls against that hundred-per-minute budget, and each one written to Outlook as a standalone appointment. A change to the series becomes a change to every instance.
Not expanded, the flow receives the series but the create action has no recurrence field to write it with, so there is nothing useful to do with it.
The realistic answer is to decide deliberately. Expand, bound the window tightly, and accept that recurring meetings arrive as copies. Or exclude recurring events from the sync and create them by hand on both sides. Flows that try to reconstruct recurrence rules from expanded instances are where most of these projects stall.
What a sync flow costs to own
Set the expectations right and this approach earns its place. It runs without a Mac being awake, it can sync accounts that belong to different organizations, and the logic is yours to change.
The ongoing cost is real too. Someone has to watch the run history, because a flow that fails silently for three weeks produces a calendar that looks right and is not. Someone has to re-authenticate the connections when a password changes or a token is revoked. Someone has to widen the date window when the business changes, and reconcile by hand after every outage. A two-way sync with echo suppression and an identity table is a small application, and it needs an owner.
The alternative worth weighing is not a different flow. It is not syncing at all. A desktop calendar that connects both accounts directly shows two organizations in one grid with no copies to reconcile, because nothing is being copied. Where the accounts are all Google, a native Mac calendar handles multiple accounts in a single view with full read and write, which the Features page sets out. Where a genuine Microsoft account has to appear alongside them, a published ICS subscription from Outlook gives a read-only layer without any automation to maintain, and the trade-offs between the Mac calendars that handle this are laid out on Compared with other calendars.
What to change first
Before building, write down the window you will sync, the fields you will carry, and how the flow will recognise its own writes, because those three decisions determine whether the result holds up. If the aim is only to see two schedules in one place rather than to have events genuinely exist in both systems, a subscription or a calendar app that connects both accounts removes the maintenance entirely, and Caltimate is one of the Mac calendars built that way.
Frequently asked questions
Can Power Automate sync Google Calendar and Outlook in both directions?
Yes, with two flows, one triggered on each side. The part that has to be designed rather than assembled is echo suppression: each flow must recognise the events written by the other, either through a marker in the description or through a stored table pairing the two event IDs. Without it, a single meeting multiplies on every pass.
How fast does the sync run?
The Google Calendar connector publishes a trigger poll frequency of one per ninety seconds, so ninety seconds is the floor rather than a typical figure. The Office 365 Outlook documentation notes that triggers fire almost immediately in most cases but can be delayed up to an hour in rare circumstances. Treat the sync as aligning two calendars over the day, not within the minute.
Why do the synced events lose their reminders and their Meet links?
The Google Calendar connector's event definition does not include reminders, recurrence, time zone, conferencing data, or a free-or-busy marker. Only title, start, end, description, location, status, attendees, creator, organizer, and the identifiers cross. Anything not on that list cannot be carried by the flow, whatever the event contained originally.
What happens when the flow hits the throttling limit?
The Google Calendar connector allows 100 API calls per connection per 60 seconds. Actions beyond that fail rather than queue, which typically leaves a sync pass half finished. Backfills and recovery runs after an outage are where this shows up, so bound each pass by a date window rather than trying to process a whole calendar at once.
Is it better to sync with a flow or subscribe to the other calendar?
They solve different problems. A flow creates real events in the destination calendar that can be edited there, at the cost of maintenance and missing fields. A subscription gives a read-only view that needs no upkeep and refreshes on the subscribing app's schedule. If the goal is seeing availability rather than owning the events twice, a subscription is usually the lighter answer.