A webhook relay you can run on your own server. It replies right away and delivers in the background: if Discord returns a 429 or the connection drops, the message waits in the queue and goes out later. Message order is preserved, and every webhook gets its own queue: separate webhooks are delivered concurrently and never block each other. Everything pauses at once only on a Discord global rate limit.

Build

git clone "https://github.com/lashkinse/discord-proxy.git"
cd discord-proxy
.\build.bat   # -> artifacts\publish\DiscordProxy.exe

Copy the whole artifacts\publish folder to your server: appsettings.json must stay next to the exe.

Configuration

Everything lives in the Proxy section of appsettings.json:

{
  "Proxy": {
    "Port": 7070,
    "DbPath": "queue.db",
    "MaxPayloadBytes": 65536,
    "MaxPending": 10000,
    "PaceSeconds": 2.2,
    "MaxAttemptsNet": 48,
    "MaxAttempts429": 25,
    "DiscordTimeoutSeconds": 15
  }
}

The defaults rarely need changing:

  • Port - the port the proxy listens on;
  • PaceSeconds - pacing between deliveries of a single webhook (2.2 s is Discord’s official limit);
  • MaxAttempts429 / MaxAttemptsNet - how many times to retry on rate limit and on network/5xx errors;
  • MaxPending - the maximum number of messages waiting in the queue.

The config is read at startup only: a change requires a restart.

Run

.\DiscordProxy.exe
.\DiscordProxy.exe --Proxy:Port=8080 --Proxy:DbPath=D:\discord\queue.db

As a Windows service - the WinSW wrapper is bundled, no extra tools needed; from the artifacts\publish folder in an administrator console:

.\install_service.bat

The DiscordProxySvc service starts automatically and restarts 10 seconds after a failure. Logs go to logs\proxy-DATE.log. To remove it:

.\uninstall_service.bat

Connecting it

Only the host changes, the request format stays Discord-native:

- https://discord.com/api/webhooks/<id>/<token>
+ http://localhost:7070/api/webhooks/<id>/<token>

The same URL works for any client that can post webhooks: a game server, a CI script, a cron job, a home bot.

Health checks and diagnostics

curl http://localhost:7070/health/ready
curl http://localhost:7070/stats

/stats is the indicator to watch: a growing dead counter means Discord rejects something permanently, i.e. a wrong token or a deleted webhook.

🔗 Source code and documentation: github.com/lashkinse/discord-proxy