Zero-Downtime Azure Functions: Watch Mode with Rider and Watchman

Working with Azure Functions locally can feel like Groundhog Day — every change means stopping and restarting your host, waiting for all the triggers to reinitialize, and only then jumping back into that bug you were fixing. What if you could get “watch mode” for Azure Functions, à la Webpack or nodemon, so your function app hot-reloads on file changes? In this post, we’ll show you how to wire up Watchman together with JetBrains Rider (or any IDE that can run external tools) to achieve zero-downtime local development for your Azure Functions.

The problem: Too many restarts

By default, you run your function project with this:

func start

…and every time you tweak a C# file or a binding configuration, you have to kill that host, rebuild, then func start again. Even with fast builds, you lose your in-memory state, open HTTP connections, and any in-flight data. For teams in a rapid-feedback loop—debugging triggers, experimenting with DI containers, mocking integrations — those seconds add up.

The solution overview: Watch + Restart

We’re going to:

  • Install Watchman to watch your source files for changes.
  • Write a small script that triggers a rebuild and restarts func start when a change occurs.
  • Hook it into Rider as an External Tool, so you can launch your Functions in watch mode with one click (or keybinding).

Under the hood, Watchman watches your directory tree with OS-level file notifications (no polling!) and invokes your script whenever it sees a modification in your .cs, .csproj, or local.settings.json.

1. Install Watchman

  • macOS (via Homebrew)

    brew install watchman
  • Windows (via Scoop)

    scoop install watchman

Verify it’s on your path:

watchman --version
# e.g. 2024.06.10.00

2. Create your watch-and-restart script

In your function app root, add watch-func.sh (or .bat on Windows). Here’s a bash example:

#!/usr/bin/env bash

# kill any existing func host
if [ -n $FUNC_PID” ]; then
kill $FUNC_PID 2>/dev/null
fi

# build the project
dotnet build –no-restore

# start Functions host in background
func start &
FUNC_PID=$!

# watch for changes
watchman-make \
–pattern=‘*.cs’ –pattern=‘*.csproj’ –pattern=‘local.settings.json’ \
–run ‘./watch-func.sh’

A few notes:

  • We use an environment variable FUNC_PID to track and kill the old host.

  • watchman-make batches file changes so rapid‐fire saves don’t hammer your script.

  • You can tweak the --pattern flags to include other file types (e.g. .json, .fs, etc.).

If you’re on Windows PowerShell, you can replicate this with a .ps1 script using Register-ObjectEvent or use watchman.exe similarly.

Make your script executable:

chmod +x watch-func.sh

3. Hook it into Rider as an External Tool

  1. Open SettingsToolsExternal Tools.

  2. Click + to add a new tool:

    • Name: Azure Functions Watch

    • Program: /bin/bash

    • Arguments: "$ProjectFileDir$/watch-func.sh"

    • Working directory: $ProjectFileDir$

  3. (Optional) Assign a keyboard shortcut via SettingsKeymapExternal ToolsAzure Functions Watch.

Now you can kick off your watch mode right from within Rider. Your run window will show the dotnet build output followed by func start logs—and any edits you save will automatically rebuild and restart, without you ever reaching for the terminal.

4. Bonus: Advanced tweaks

  • Delay restarts
    If you hit build errors mid-save, add a sleep 0.5 before killing the old host to let the file settle.

  • Selective restarts
    Use Watchman’s --since flag or a custom --trigger-query to only rebuild on certain paths (e.g., skip tests folder).

  • Logging
    Pipe your script’s stdout/stderr into a rotating log file for post-mortems:

    ./watch-func.sh >> watch.log 2>&1

Conclusion

With just a few lines of script and Watchman’s blazing-fast file watcher, you can transform your Azure Functions local experience into a near hot-reload workflow. No more manual restarts, no more context loss—just save, watch, and code. Give it a spin on your next Functions project, and let us know how it works for you!

Conversation

Join the conversation

Your email address will not be published. Required fields are marked *