# Deferring

Keep an interaction open past Discord's three-second limit, then fill the reply in when your handler finishes. Covers setting ephemeral at deferral time, the throw when you call reply() after, and deferring before anything slow.

Some handlers need longer than the three seconds Discord allows for a first response. [`this.defer()`](https://docs.seedcord.org/packages/gateway/latest/repliable-handler#defer) answers inside that with a loading state, which leaves the real reply for later.

```ts title="src/handlers/Ban.ts"
import { SlashHandler, SlashRoute } from '@seedcord/gateway';

@SlashRoute('ban')
export class Ban extends SlashHandler<'ban'> {
    public async execute(): Promise<void> {
        await this.defer();

        const target = this.options.getUser('target');
        const priors = await countPriorBans(target.id);

        await this.edit(
            `Banned ${target.username}. ${priors} bans before this one.`
        );
    }
}
```

The person who ran the command sees your bot thinking until [`edit()`](https://docs.seedcord.org/packages/gateway/latest/repliable-handler#edit) runs. Discord expires the interaction token fifteen minutes after the interaction, so every call you make on it has to arrive before then.

## Set ephemeral when you defer

`defer()` takes an `ephemeral` option, and it's on by default. Only the person who ran the command sees the placeholder and the reply that fills it.

```ts
await this.defer({ ephemeral: false });
```

`edit()` doesn't take options, so whatever you pass `defer()` is what the reply carries.

## reply() after a deferral throws

The deferral was the initial response. `edit()` rewrites it.

```txt output
reply() was called when this interaction was already deferred.
Use edit() to fill the deferred reply or followUp() for a new
message. (route slash:ban)
```

[`followUp()`](https://docs.seedcord.org/packages/gateway/latest/repliable-handler#follow-up) sends a second message beside the first, and [`delete()`](https://docs.seedcord.org/packages/gateway/latest/repliable-handler#delete) removes the loading state. [The full table](/replying/ack-states) lists every state and how you reach it.

## Defer before anything slow

[`reply()`](https://docs.seedcord.org/packages/gateway/latest/repliable-handler#reply) after the three seconds throws Discord's own error, `DiscordAPIError[10062]`, since the interaction is gone by then. seedcord rethrows it untouched, then sends its [error card](/replying/faults) to that same interaction. Discord rejects the card too, and seedcord drops that rejection with a debug line. The person who ran the command sees the interaction fail.

Defer first whenever you can't predict how long the handler takes.
