diff --git a/docs/source/building/macos.rst b/docs/source/building/macos.rst
index c2a0adbbd2e..6d90a651b25 100644
--- a/docs/source/building/macos.rst
+++ b/docs/source/building/macos.rst
@@ -12,7 +12,7 @@ MacPorts
 Install Requirements
    .. code-block:: bash
 
-      sudo port install avahi cmake curl doxygen graphviz libopus miniupnpc npm9 pkgconfig python311 py311-pip
+      sudo port install cmake curl doxygen graphviz libopus miniupnpc npm9 pkgconfig python311 py311-pip
 
 Homebrew
 """"""""
diff --git a/packaging/macos/Portfile b/packaging/macos/Portfile
index 4a89b1d8848..3fdb7b93718 100644
--- a/packaging/macos/Portfile
+++ b/packaging/macos/Portfile
@@ -38,8 +38,7 @@ depends_build-append     port:doxygen \
                          port:python311 \
                          port:py311-pip
 
-depends_lib              port:avahi \
-                         port:curl \
+depends_lib              port:curl \
                          port:libopus \
                          port:miniupnpc
 
diff --git a/packaging/sunshine.rb b/packaging/sunshine.rb
index 78d8f3e75bb..cb97f7f097a 100644
--- a/packaging/sunshine.rb
+++ b/packaging/sunshine.rb
@@ -37,6 +37,7 @@ class @PROJECT_NAME@ < Formula
   depends_on "icu4c" => :recommended
 
   on_linux do
+    depends_on "avahi"
     depends_on "libcap"
     depends_on "libdrm"
     depends_on "libnotify"
diff --git a/src/platform/linux/publish.cpp b/src/platform/linux/publish.cpp
index 2115ec8a798..29641411e50 100644
--- a/src/platform/linux/publish.cpp
+++ b/src/platform/linux/publish.cpp
@@ -2,7 +2,6 @@
  * @file src/platform/linux/publish.cpp
  * @brief Definitions for publishing services on Linux.
  * @note Adapted from https://www.avahi.org/doxygen/html/client-publish-service_8c-example.html
- * @todo Use a common file for this and src/platform/macos/publish.cpp
  */
 #include <thread>
 
diff --git a/src/platform/macos/publish.cpp b/src/platform/macos/publish.cpp
index 3eda292bf73..ec4f1f452dd 100644
--- a/src/platform/macos/publish.cpp
+++ b/src/platform/macos/publish.cpp
@@ -1,442 +1,123 @@
 /**
  * @file src/platform/macos/publish.cpp
  * @brief Definitions for publishing services on macOS.
- * @note Adapted from https://www.avahi.org/doxygen/html/client-publish-service_8c-example.html
- * @todo Use a common file for this and src/platform/linux/publish.cpp
  */
+#include <dns_sd.h>
 #include <thread>
 
-#include "misc.h"
 #include "src/logging.h"
 #include "src/network.h"
 #include "src/nvhttp.h"
 #include "src/platform/common.h"
-#include "src/utility.h"
 
 using namespace std::literals;
 
-namespace avahi {
-
-  /**
-   * @brief Error codes used by avahi.
-   */
-  enum err_e {
-    OK = 0,  ///< OK
-    ERR_FAILURE = -1,  ///< Generic error code
-    ERR_BAD_STATE = -2,  ///< Object was in a bad state
-    ERR_INVALID_HOST_NAME = -3,  ///< Invalid host name
-    ERR_INVALID_DOMAIN_NAME = -4,  ///< Invalid domain name
-    ERR_NO_NETWORK = -5,  ///< No suitable network protocol available
-    ERR_INVALID_TTL = -6,  ///< Invalid DNS TTL
-    ERR_IS_PATTERN = -7,  ///< RR key is pattern
-    ERR_COLLISION = -8,  ///< Name collision
-    ERR_INVALID_RECORD = -9,  ///< Invalid RR
-
-    ERR_INVALID_SERVICE_NAME = -10,  ///< Invalid service name
-    ERR_INVALID_SERVICE_TYPE = -11,  ///< Invalid service type
-    ERR_INVALID_PORT = -12,  ///< Invalid port number
-    ERR_INVALID_KEY = -13,  ///< Invalid key
-    ERR_INVALID_ADDRESS = -14,  ///< Invalid address
-    ERR_TIMEOUT = -15,  ///< Timeout reached
-    ERR_TOO_MANY_CLIENTS = -16,  ///< Too many clients
-    ERR_TOO_MANY_OBJECTS = -17,  ///< Too many objects
-    ERR_TOO_MANY_ENTRIES = -18,  ///< Too many entries
-    ERR_OS = -19,  ///< OS error
-
-    ERR_ACCESS_DENIED = -20,  ///< Access denied
-    ERR_INVALID_OPERATION = -21,  ///< Invalid operation
-    ERR_DBUS_ERROR = -22,  ///< An unexpected D-Bus error occurred
-    ERR_DISCONNECTED = -23,  ///< Daemon connection failed
-    ERR_NO_MEMORY = -24,  ///< Memory exhausted
-    ERR_INVALID_OBJECT = -25,  ///< The object passed to this function was invalid
-    ERR_NO_DAEMON = -26,  ///< Daemon not running
-    ERR_INVALID_INTERFACE = -27,  ///< Invalid interface
-    ERR_INVALID_PROTOCOL = -28,  ///< Invalid protocol
-    ERR_INVALID_FLAGS = -29,  ///< Invalid flags
-
-    ERR_NOT_FOUND = -30,  ///< Not found
-    ERR_INVALID_CONFIG = -31,  ///< Configuration error
-    ERR_VERSION_MISMATCH = -32,  ///< Version mismatch
-    ERR_INVALID_SERVICE_SUBTYPE = -33,  ///< Invalid service subtype
-    ERR_INVALID_PACKET = -34,  ///< Invalid packet
-    ERR_INVALID_DNS_ERROR = -35,  ///< Invalid DNS return code
-    ERR_DNS_FORMERR = -36,  ///< DNS Error: Form error
-    ERR_DNS_SERVFAIL = -37,  ///< DNS Error: Server Failure
-    ERR_DNS_NXDOMAIN = -38,  ///< DNS Error: No such domain
-    ERR_DNS_NOTIMP = -39,  ///< DNS Error: Not implemented
-
-    ERR_DNS_REFUSED = -40,  ///< DNS Error: Operation refused
-    ERR_DNS_YXDOMAIN = -41,  ///< TODO
-    ERR_DNS_YXRRSET = -42,  ///< TODO
-    ERR_DNS_NXRRSET = -43,  ///< TODO
-    ERR_DNS_NOTAUTH = -44,  ///< DNS Error: Not authorized
-    ERR_DNS_NOTZONE = -45,  ///< TODO
-    ERR_INVALID_RDATA = -46,  ///< Invalid RDATA
-    ERR_INVALID_DNS_CLASS = -47,  ///< Invalid DNS class
-    ERR_INVALID_DNS_TYPE = -48,  ///< Invalid DNS type
-    ERR_NOT_SUPPORTED = -49,  ///< Not supported
-
-    ERR_NOT_PERMITTED = -50,  ///< Operation not permitted
-    ERR_INVALID_ARGUMENT = -51,  ///< Invalid argument
-    ERR_IS_EMPTY = -52,  ///< Is empty
-    ERR_NO_CHANGE = -53,  ///< The requested operation is invalid because it is redundant
-
-    ERR_MAX = -54  ///< TODO
-  };
-
-  constexpr auto IF_UNSPEC = -1;
-  enum proto {
-    PROTO_INET = 0,  ///< IPv4
-    PROTO_INET6 = 1,  ///< IPv6
-    PROTO_UNSPEC = -1  ///< Unspecified/all protocol(s)
-  };
-
-  enum ServerState {
-    SERVER_INVALID,  ///< Invalid state (initial)
-    SERVER_REGISTERING,  ///< Host RRs are being registered
-    SERVER_RUNNING,  ///< All host RRs have been established
-    SERVER_COLLISION,  ///< There is a collision with a host RR. All host RRs have been withdrawn, the user should set a new host name via avahi_server_set_host_name()
-    SERVER_FAILURE  ///< Some fatal failure happened, the server is unable to proceed
-  };
-
-  enum ClientState {
-    CLIENT_S_REGISTERING = SERVER_REGISTERING,  ///< Server state: REGISTERING
-    CLIENT_S_RUNNING = SERVER_RUNNING,  ///< Server state: RUNNING
-    CLIENT_S_COLLISION = SERVER_COLLISION,  ///< Server state: COLLISION
-    CLIENT_FAILURE = 100,  ///< Some kind of error happened on the client side
-    CLIENT_CONNECTING = 101  ///< We're still connecting. This state is only entered when AVAHI_CLIENT_NO_FAIL has been passed to avahi_client_new() and the daemon is not yet available.
-  };
-
-  enum EntryGroupState {
-    ENTRY_GROUP_UNCOMMITED,  ///< The group has not yet been committed, the user must still call avahi_entry_group_commit()
-    ENTRY_GROUP_REGISTERING,  ///< The entries of the group are currently being registered
-    ENTRY_GROUP_ESTABLISHED,  ///< The entries have successfully been established
-    ENTRY_GROUP_COLLISION,  ///< A name collision for one of the entries in the group has been detected, the entries have been withdrawn
-    ENTRY_GROUP_FAILURE  ///< Some kind of failure happened, the entries have been withdrawn
-  };
-
-  enum ClientFlags {
-    CLIENT_IGNORE_USER_CONFIG = 1,  ///< Don't read user configuration
-    CLIENT_NO_FAIL = 2  ///< Don't fail if the daemon is not available when avahi_client_new() is called, instead enter CLIENT_CONNECTING state and wait for the daemon to appear
-  };
-
-  /**
-   * @brief Flags for publishing functions.
-   */
-  enum PublishFlags {
-    PUBLISH_UNIQUE = 1,  ///< For raw records: The RRset is intended to be unique
-    PUBLISH_NO_PROBE = 2,  ///< For raw records: Though the RRset is intended to be unique no probes shall be sent
-    PUBLISH_NO_ANNOUNCE = 4,  ///< For raw records: Do not announce this RR to other hosts
-    PUBLISH_ALLOW_MULTIPLE = 8,  ///< For raw records: Allow multiple local records of this type, even if they are intended to be unique
-    PUBLISH_NO_REVERSE = 16,  ///< For address records: don't create a reverse (PTR) entry
-    PUBLISH_NO_COOKIE = 32,  ///< For service records: do not implicitly add the local service cookie to TXT data
-    PUBLISH_UPDATE = 64,  ///< Update existing records instead of adding new ones
-    PUBLISH_USE_WIDE_AREA = 128,  ///< Register the record using wide area DNS (i.e. unicast DNS update)
-    PUBLISH_USE_MULTICAST = 256  ///< Register the record using multicast DNS
-  };
-
-  using IfIndex = int;
-  using Protocol = int;
-
-  struct EntryGroup;
-  struct Poll;
-  struct SimplePoll;
-  struct Client;
-
-  typedef void (*ClientCallback)(Client *, ClientState, void *userdata);
-  typedef void (*EntryGroupCallback)(EntryGroup *g, EntryGroupState state, void *userdata);
-
-  typedef void (*free_fn)(void *);
-
-  typedef Client *(*client_new_fn)(const Poll *poll_api, ClientFlags flags, ClientCallback callback, void *userdata, int *error);
-  typedef void (*client_free_fn)(Client *);
-  typedef char *(*alternative_service_name_fn)(char *);
-
-  typedef Client *(*entry_group_get_client_fn)(EntryGroup *);
-
-  typedef EntryGroup *(*entry_group_new_fn)(Client *, EntryGroupCallback, void *userdata);
-  typedef int (*entry_group_add_service_fn)(
-    EntryGroup *group,
-    IfIndex interface,
-    Protocol protocol,
-    PublishFlags flags,
-    const char *name,
-    const char *type,
-    const char *domain,
-    const char *host,
-    uint16_t port,
-    ...);
-
-  typedef int (*entry_group_is_empty_fn)(EntryGroup *);
-  typedef int (*entry_group_reset_fn)(EntryGroup *);
-  typedef int (*entry_group_commit_fn)(EntryGroup *);
-
-  typedef char *(*strdup_fn)(const char *);
-  typedef char *(*strerror_fn)(int);
-  typedef int (*client_errno_fn)(Client *);
-
-  typedef Poll *(*simple_poll_get_fn)(SimplePoll *);
-  typedef int (*simple_poll_loop_fn)(SimplePoll *);
-  typedef void (*simple_poll_quit_fn)(SimplePoll *);
-  typedef SimplePoll *(*simple_poll_new_fn)();
-  typedef void (*simple_poll_free_fn)(SimplePoll *);
-
-  free_fn free;
-  client_new_fn client_new;
-  client_free_fn client_free;
-  alternative_service_name_fn alternative_service_name;
-  entry_group_get_client_fn entry_group_get_client;
-  entry_group_new_fn entry_group_new;
-  entry_group_add_service_fn entry_group_add_service;
-  entry_group_is_empty_fn entry_group_is_empty;
-  entry_group_reset_fn entry_group_reset;
-  entry_group_commit_fn entry_group_commit;
-  strdup_fn strdup;
-  strerror_fn strerror;
-  client_errno_fn client_errno;
-  simple_poll_get_fn simple_poll_get;
-  simple_poll_loop_fn simple_poll_loop;
-  simple_poll_quit_fn simple_poll_quit;
-  simple_poll_new_fn simple_poll_new;
-  simple_poll_free_fn simple_poll_free;
-
-  int
-  init_common() {
-    static void *handle { nullptr };
-    static bool funcs_loaded = false;
-
-    if (funcs_loaded) return 0;
-
-    if (!handle) {
-      handle = dyn::handle({ "libavahi-common.3.dylib", "libavahi-common.dylib" });
-      if (!handle) {
-        return -1;
+namespace platf::publish {
+  namespace {
+    /** @brief Custom deleter intended to be used for `std::unique_ptr<DNSServiceRef>`. */
+    struct ServiceRefDeleter {
+      typedef DNSServiceRef pointer;  ///< Type of object to be deleted.
+      void
+      operator()(pointer serviceRef) {
+        DNSServiceRefDeallocate(serviceRef);
+        BOOST_LOG(info) << "Deregistered DNS service."sv;
       }
-    }
-
-    std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
-      { (dyn::apiproc *) &alternative_service_name, "avahi_alternative_service_name" },
-      { (dyn::apiproc *) &free, "avahi_free" },
-      { (dyn::apiproc *) &strdup, "avahi_strdup" },
-      { (dyn::apiproc *) &strerror, "avahi_strerror" },
-      { (dyn::apiproc *) &simple_poll_get, "avahi_simple_poll_get" },
-      { (dyn::apiproc *) &simple_poll_loop, "avahi_simple_poll_loop" },
-      { (dyn::apiproc *) &simple_poll_quit, "avahi_simple_poll_quit" },
-      { (dyn::apiproc *) &simple_poll_new, "avahi_simple_poll_new" },
-      { (dyn::apiproc *) &simple_poll_free, "avahi_simple_poll_free" },
     };
-
-    if (dyn::load(handle, funcs)) {
-      return -1;
-    }
-
-    funcs_loaded = true;
-    return 0;
-  }
-
-  int
-  init_client() {
-    if (init_common()) {
-      return -1;
-    }
-
-    static void *handle { nullptr };
-    static bool funcs_loaded = false;
-
-    if (funcs_loaded) return 0;
-
-    if (!handle) {
-      handle = dyn::handle({ "libavahi-client.3.dylib", "libavahi-client.dylib" });
-      if (!handle) {
-        return -1;
+    /** @brief This class encapsulates the polling and deinitialization of our connection with
+     *         the mDNS service. Implements the `::platf::deinit_t` interface.
+     */
+    class deinit_t: public ::platf::deinit_t, std::unique_ptr<DNSServiceRef, ServiceRefDeleter> {
+    public:
+      /** @brief Construct deinit_t object.
+       *
+       * Create a thread that will use `select(2)` to wait for a response from the mDNS service.
+       * The thread will give up if an error is received or if `_stopRequested` becomes true.
+       *
+       * @param serviceRef An initialized reference to the mDNS service.
+       */
+      deinit_t(DNSServiceRef serviceRef):
+          unique_ptr(serviceRef) {
+        _thread = std::thread { [serviceRef, &_stopRequested = std::as_const(_stopRequested)]() {
+          const auto socket = DNSServiceRefSockFD(serviceRef);
+          while (!_stopRequested) {
+            auto fdset = fd_set {};
+            FD_ZERO(&fdset);
+            FD_SET(socket, &fdset);
+            auto timeout = timeval { .tv_sec = 3, .tv_usec = 0 };  // 3 second timeout
+            const auto ready = select(socket + 1, &fdset, nullptr, nullptr, &timeout);
+            if (ready == -1) {
+              BOOST_LOG(error) << "Failed to obtain response from DNS service."sv;
+              break;
+            }
+            else if (ready != 0) {
+              DNSServiceProcessResult(serviceRef);
+              break;
+            }
+          }
+        } };
       }
-    }
-
-    std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
-      { (dyn::apiproc *) &client_new, "avahi_client_new" },
-      { (dyn::apiproc *) &client_free, "avahi_client_free" },
-      { (dyn::apiproc *) &entry_group_get_client, "avahi_entry_group_get_client" },
-      { (dyn::apiproc *) &entry_group_new, "avahi_entry_group_new" },
-      { (dyn::apiproc *) &entry_group_add_service, "avahi_entry_group_add_service" },
-      { (dyn::apiproc *) &entry_group_is_empty, "avahi_entry_group_is_empty" },
-      { (dyn::apiproc *) &entry_group_reset, "avahi_entry_group_reset" },
-      { (dyn::apiproc *) &entry_group_commit, "avahi_entry_group_commit" },
-      { (dyn::apiproc *) &client_errno, "avahi_client_errno" },
-    };
-
-    if (dyn::load(handle, funcs)) {
-      return -1;
-    }
-
-    funcs_loaded = true;
-    return 0;
-  }
-}  // namespace avahi
-
-namespace platf::publish {
-
-  template <class T>
-  void
-  free(T *p) {
-    avahi::free(p);
-  }
-
-  template <class T>
-  using ptr_t = util::safe_ptr<T, free<T>>;
-  using client_t = util::dyn_safe_ptr<avahi::Client, &avahi::client_free>;
-  using poll_t = util::dyn_safe_ptr<avahi::SimplePoll, &avahi::simple_poll_free>;
-
-  avahi::EntryGroup *group = nullptr;
-
-  poll_t poll;
-  client_t client;
-
-  ptr_t<char> name;
-
-  void
-  create_services(avahi::Client *c);
-
-  void
-  entry_group_callback(avahi::EntryGroup *g, avahi::EntryGroupState state, void *) {
-    group = g;
-
-    switch (state) {
-      case avahi::ENTRY_GROUP_ESTABLISHED:
-        BOOST_LOG(info) << "Avahi service " << name.get() << " successfully established.";
-        break;
-      case avahi::ENTRY_GROUP_COLLISION:
-        name.reset(avahi::alternative_service_name(name.get()));
-
-        BOOST_LOG(info) << "Avahi service name collision, renaming service to " << name.get();
-
-        create_services(avahi::entry_group_get_client(g));
-        break;
-      case avahi::ENTRY_GROUP_FAILURE:
-        BOOST_LOG(error) << "Avahi entry group failure: " << avahi::strerror(avahi::client_errno(avahi::entry_group_get_client(g)));
-        avahi::simple_poll_quit(poll.get());
-        break;
-      case avahi::ENTRY_GROUP_UNCOMMITED:
-      case avahi::ENTRY_GROUP_REGISTERING:;
-    }
-  }
-
-  void
-  create_services(avahi::Client *c) {
-    int ret;
-
-    auto fg = util::fail_guard([]() {
-      avahi::simple_poll_quit(poll.get());
-    });
-
-    if (!group) {
-      if (!(group = avahi::entry_group_new(c, entry_group_callback, nullptr))) {
-        BOOST_LOG(error) << "avahi::entry_group_new() failed: "sv << avahi::strerror(avahi::client_errno(c));
-        return;
+      /** @brief Ensure that we gracefully finish polling the mDNS service before freeing our
+       *         connection to it.
+       */
+      ~deinit_t() override {
+        _stopRequested = true;
+        _thread.join();
       }
-    }
-
-    if (avahi::entry_group_is_empty(group)) {
-      BOOST_LOG(info) << "Adding avahi service "sv << name.get();
-
-      ret = avahi::entry_group_add_service(
-        group,
-        avahi::IF_UNSPEC, avahi::PROTO_UNSPEC,
-        avahi::PublishFlags(0),
-        name.get(),
-        SERVICE_TYPE,
-        nullptr, nullptr,
-        net::map_port(nvhttp::PORT_HTTP),
-        nullptr);
+      deinit_t(const deinit_t &) = delete;
+      deinit_t &
+      operator=(const deinit_t &) = delete;
 
-      if (ret < 0) {
-        if (ret == avahi::ERR_COLLISION) {
-          // A service name collision with a local service happened. Let's pick a new name
-          name.reset(avahi::alternative_service_name(name.get()));
-          BOOST_LOG(info) << "Service name collision, renaming service to "sv << name.get();
-
-          avahi::entry_group_reset(group);
-
-          create_services(c);
-
-          fg.disable();
-          return;
-        }
-
-        BOOST_LOG(error) << "Failed to add "sv << SERVICE_TYPE << " service: "sv << avahi::strerror(ret);
-        return;
-      }
+    private:
+      std::thread _thread;  ///< Thread for polling the mDNS service for a response.
+      std::atomic<bool> _stopRequested = false;  ///< Whether to stop polling the mDNS service.
+    };
 
-      ret = avahi::entry_group_commit(group);
-      if (ret < 0) {
-        BOOST_LOG(error) << "Failed to commit entry group: "sv << avahi::strerror(ret);
+    /** @brief Callback that will be invoked when the mDNS service finishes registering our service.
+     *  @param errorCode Describes whether the registration was successful.
+     */
+    void
+    registrationCallback(DNSServiceRef /*serviceRef*/, DNSServiceFlags /*flags*/,
+      DNSServiceErrorType errorCode, const char * /*name*/,
+      const char * /*regtype*/, const char * /*domain*/, void * /*context*/) {
+      if (errorCode != kDNSServiceErr_NoError) {
+        BOOST_LOG(error) << "Failed to register DNS service: Error "sv << errorCode;
         return;
       }
+      BOOST_LOG(info) << "Successfully registered DNS service."sv;
     }
+  }  // anonymous namespace
 
-    fg.disable();
-  }
-
-  void
-  client_callback(avahi::Client *c, avahi::ClientState state, void *) {
-    switch (state) {
-      case avahi::CLIENT_S_RUNNING:
-        create_services(c);
-        break;
-      case avahi::CLIENT_FAILURE:
-        BOOST_LOG(error) << "Client failure: "sv << avahi::strerror(avahi::client_errno(c));
-        avahi::simple_poll_quit(poll.get());
-        break;
-      case avahi::CLIENT_S_COLLISION:
-      case avahi::CLIENT_S_REGISTERING:
-        if (group)
-          avahi::entry_group_reset(group);
-        break;
-      case avahi::CLIENT_CONNECTING:;
-    }
-  }
-
-  class deinit_t: public ::platf::deinit_t {
-  public:
-    std::thread poll_thread;
-
-    explicit deinit_t(std::thread poll_thread):
-        poll_thread { std::move(poll_thread) } {}
-
-    ~deinit_t() override {
-      if (avahi::simple_poll_quit && poll) {
-        avahi::simple_poll_quit(poll.get());
-      }
-
-      if (poll_thread.joinable()) {
-        poll_thread.join();
-      }
-    }
-  };
-
+  /**
+   * @brief Main entry point for publication of our service on macOS.
+   *
+   * This function initiates a connection to the macOS mDNS service and requests to register
+   * our Sunshine service. Registration will occur asynchronously (unless it fails immediately,
+   * which is probably only possible if the host machine is misconfigured).
+   *
+   * @return Either `nullptr` (if the registration fails immediately) or a `uniqur_ptr<deinit_t>`,
+   *         which will manage polling for a response from the mDNS service, and then, when
+   *         deconstructed, will deregister the service.
+   */
   [[nodiscard]] std::unique_ptr<::platf::deinit_t>
   start() {
-    if (avahi::init_client()) {
-      return nullptr;
-    }
-
-    int avhi_error;
-
-    poll.reset(avahi::simple_poll_new());
-    if (!poll) {
-      BOOST_LOG(error) << "Failed to create simple poll object."sv;
+    auto serviceRef = DNSServiceRef {};
+    const auto status = DNSServiceRegister(
+      &serviceRef,
+      0,  // flags
+      0,  // interfaceIndex
+      SERVICE_NAME, SERVICE_TYPE,
+      nullptr,  // domain
+      nullptr,  // host
+      htons(net::map_port(nvhttp::PORT_HTTP)),
+      0,  // txtLen
+      nullptr,  // txtRecord
+      registrationCallback,
+      nullptr  // context
+    );
+    if (status != kDNSServiceErr_NoError) {
+      BOOST_LOG(error) << "Failed immediately to register DNS service: Error "sv << status;
       return nullptr;
     }
-
-    name.reset(avahi::strdup(SERVICE_NAME));
-
-    client.reset(
-      avahi::client_new(avahi::simple_poll_get(poll.get()), avahi::ClientFlags(0), client_callback, nullptr, &avhi_error));
-
-    if (!client) {
-      BOOST_LOG(error) << "Failed to create client: "sv << avahi::strerror(avhi_error);
-      return nullptr;
-    }
-
-    return std::make_unique<deinit_t>(std::thread { avahi::simple_poll_loop, poll.get() });
+    return std::make_unique<deinit_t>(serviceRef);
   }
 }  // namespace platf::publish