Skip to main content
When a workspace uninstalls your app, Attio calls the same handlers that it calls when a workflow is paused or a connection is removed. There is no separate uninstall event. If your deactivate and connection-removed handlers clean up what your app created, that cleanup also runs on uninstall.

What happens on uninstall

Attio uninstalls an app in this order:
  1. Pause workflows. Attio pauses every live workflow that uses your app. As with a manual pause, it calls deactivate for each trigger block in the workflow.
  2. Wait for teardowns. Attio waits for each deactivate call to finish, for up to 10 minutes.
  3. Remove connections. Attio removes every connection of the installation, both workspace and user connections. It calls connection-removed for each one before it removes the connection.

Where to put your cleanup

Use this table to find the handler that must delete each resource: For example, if a trigger block registers a webhook for one workflow, delete that webhook in deactivate. Use the uniqueActivationId from metadata to find it. If your app registers a webhook one time for each connection, delete that webhook in connection-removed.
Attio also calls connection-removed when a user reconnects. If connection-removed deletes a trigger block’s webhooks, every workflow that uses them stops triggering, even though the workflow is still live. Delete those webhooks in deactivate instead.

When cleanup fails

deactivate

  • If deactivate returns {type: "error"}, Attio does not call it again.
  • If deactivate throws, Attio calls it again, for a maximum of 5 attempts. There is no delay between attempts. Thus, the attempts help only with failures that continue for a few seconds or less.
In both cases, the workflow stays paused and the uninstall continues.

connection-removed

During an uninstall, Attio always removes the connection:
  • If connection-removed throws, Attio calls it again, for a maximum of 5 attempts. The minimum time between attempts is 30 seconds. After the last attempt, Attio removes the connection.
  • If connection-removed runs for longer than the 30-second server function timeout, Attio stops it. Unlike a throw, a timeout is not retried: Attio removes the connection.
  • In two cases, connection-removed cannot run, so Attio removes the connection without it and your cleanup does not happen:
    • The member who created the connection is not an active member of the workspace now. connection-removed runs as this member.
    • The OAuth access token of the connection is expired, and Attio cannot refresh it. connection-removed cannot use the connection.
In other situations, if connection-removed throws, Attio does not remove the connection. See connection-removed.

Make cleanup safe to repeat

Attio can call deactivate and connection-removed more than one time. Make sure that your cleanup code is safe to run again:
  • If the third-party service returns “not found”, do not throw or return an error. Possibly, the resource is already deleted.
  • Store the IDs that you need for cleanup when you create the resource. One way to do this is with the KV store: in activate, you could save the external webhook ID under a key that includes the uniqueActivationId. Then in deactivate, you could read the ID, delete the webhook, and delete the key. If the key is not there, the cleanup is already done.
  • For a webhook that your app registers for each connection, save the ID as the webhook handler’s externalWebhookId.