diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 8c077af6f60f3f49df52663f929548884cd2572f..ba731646711fdcd361ee1f39184a1f8519c36f0c 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -769,7 +769,7 @@ JamiAccount::SIPStartCall(SIPCall& call, IpAddr target)
     if (!CreateClientDialogAndInvite(&pjFrom, &pjContact, &pjTo, &pjTarget, local_sdp, &dialog, &inv))
         return false;
 
-    inv->mod_data[link_->getModId()] = &call;
+    inv->mod_data[link_.getModId()] = &call;
     call.inv.reset(inv);
 
 /*
@@ -1594,7 +1594,7 @@ JamiAccount::handlePendingCall(PendingCall& pc, bool incoming)
 
     // Following can create a transport that need to be negotiated (TLS).
     // This is a asynchronous task. So we're going to process the SIP after this negotiation.
-    auto transport = link_->sipTransportBroker->getTlsIceTransport(best_transport,
+    auto transport = link_.sipTransportBroker->getTlsIceTransport(best_transport,
                                                                    ICE_COMP_SIP_TRANSPORT,
                                                                    tlsParams);
     if (!transport)
@@ -2785,7 +2785,7 @@ JamiAccount::sendTextMessage(const std::string& to, const std::map<std::string,
         pj_str_t pjTo = pj_str((char*) toURI.c_str());
 
         // Create request.
-        pj_status_t status = pjsip_endpt_create_request(link_->getEndpoint(), &msg_method,
+        pj_status_t status = pjsip_endpt_create_request(link_.getEndpoint(), &msg_method,
                                                         &pjTo, &pjFrom, &pjTo, nullptr, nullptr, -1,
                                                         nullptr, &tdata);
         if (status != PJ_SUCCESS) {
@@ -2850,7 +2850,7 @@ JamiAccount::sendTextMessage(const std::string& to, const std::map<std::string,
 
             sip_utils::register_thread();
 
-            auto status = pjsip_endpt_send_request(shared->link_->getEndpoint(), tdata, -1, ctx.release(),
+            auto status = pjsip_endpt_send_request(shared->link_.getEndpoint(), tdata, -1, ctx.release(),
                 [](void *token, pjsip_event *event)
                 {
                     std::unique_ptr<TextMessageCtx> c{ (TextMessageCtx*)token };
@@ -3292,7 +3292,7 @@ JamiAccount::cacheSIPConnection(std::shared_ptr<ChannelSocket>&& socket, const s
                 conn++;
         }
     };
-    auto sip_tr = link_->sipTransportBroker->getChanneledTransport(socket, std::move(onShutdown));
+    auto sip_tr = link_.sipTransportBroker->getChanneledTransport(socket, std::move(onShutdown));
     // Store the connection
     sipConnections_[peerId][deviceId].emplace_back(SipConnection {
         std::move(sip_tr),
diff --git a/src/manager.cpp b/src/manager.cpp
index 4db284d3d92e2118e6d9127f48d0f37b08bfc441..8a837c0eaefe3c4aee39cbc6288da385e08acdbb 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -41,6 +41,7 @@
 #include "account.h"
 #include "string_utils.h"
 #include "jamidht/jamiaccount.h"
+#include "sip/sipvoiplink.h"
 #include <opendht/rng.h>
 using random_device = dht::crypto::random_device;
 
@@ -412,6 +413,8 @@ struct Manager::ManagerPimpl
 #ifdef ENABLE_VIDEO
     std::unique_ptr<VideoManager> videoManager_;
 #endif
+
+    std::unique_ptr<SIPVoIPLink> sipLink_;
 };
 
 Manager::ManagerPimpl::ManagerPimpl(Manager& base)
@@ -741,6 +744,8 @@ Manager::init(const std::string &config_file)
 
     setDhtLogLevel();
 
+    pimpl_->sipLink_ = std::make_unique<SIPVoIPLink>();
+
     check_rename(fileutils::get_cache_dir(PACKAGE_OLD), fileutils::get_cache_dir());
     check_rename(fileutils::get_data_dir(PACKAGE_OLD), fileutils::get_data_dir());
     check_rename(fileutils::get_config_dir(PACKAGE_OLD), fileutils::get_config_dir());
@@ -761,7 +766,6 @@ Manager::init(const std::string &config_file)
         JAMI_ERR("%s", e.what());
         no_errors = false;
     }
-
     // Some VoIP services support SIP/TLS and SRTP, but do not set the
     // correct schema in the INVITE request. For more details, see:
     // https://trac.pjsip.org/repos/ticket/1735
@@ -776,9 +780,6 @@ Manager::init(const std::string &config_file)
         // restore previous configuration
         JAMI_WARN("Restoring last working configuration");
 
-        // keep a reference to sipvoiplink while destroying the accounts
-        const auto sipvoiplink = getSIPVoIPLink();
-
         try {
             // remove accounts from broken configuration
             removeAccounts();
@@ -3074,6 +3075,13 @@ Manager::getLastMessages(const std::string& accountID, const uint64_t& base_time
     return {};
 }
 
+SIPVoIPLink&
+Manager::sipVoIPLink() const
+{
+    return *pimpl_->sipLink_;
+}
+
+
 std::map<std::string, std::string>
 Manager::getNearbyPeers(const std::string& accountID)
 {
diff --git a/src/manager.h b/src/manager.h
index 55cfe2ebda5d7933bb6c5f87d1737f39c12737f7..dd972dfae5ea3aef082c77ad2fd3806078e42085 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -60,6 +60,7 @@ class AudioLoop;
 class IceTransportFactory;
 class DataTransferFacade;
 class JamiAccount;
+class SIPVoIPLink;
 
 static constexpr uint64_t DRING_ID_MAX_VAL = 9007199254740992;
 
@@ -900,6 +901,8 @@ class DRING_TESTABLE Manager {
 
         std::vector<DRing::Message> getLastMessages(const std::string& accountID, const uint64_t& base_timestamp);
 
+        SIPVoIPLink& sipVoIPLink() const;
+
 private:
         Manager();
         ~Manager();
diff --git a/src/sip/pres_sub_client.cpp b/src/sip/pres_sub_client.cpp
index 4e78d0526ea14ec82fd486a01d7c0ef319a9f49b..47f52b8a2dc38c4adbed62660edaf5e1403bf5a6 100644
--- a/src/sip/pres_sub_client.cpp
+++ b/src/sip/pres_sub_client.cpp
@@ -377,7 +377,7 @@ bool PresSubClient::isTermReason(const std::string &reason)
 void PresSubClient::rescheduleTimer(bool reschedule, unsigned msec)
 {
     if (timer_.id) {
-        pjsip_endpt_cancel_timer(getSIPVoIPLink()->getEndpoint(), &timer_);
+        pjsip_endpt_cancel_timer(Manager::instance().sipVoIPLink().getEndpoint(), &timer_);
         timer_.id = PJ_FALSE;
     }
 
@@ -391,7 +391,7 @@ void PresSubClient::rescheduleTimer(bool reschedule, unsigned msec)
         delay.msec = msec;
         pj_time_val_normalize(&delay);
 
-        if (pjsip_endpt_schedule_timer(getSIPVoIPLink()->getEndpoint(), &timer_, &delay) == PJ_SUCCESS) {
+        if (pjsip_endpt_schedule_timer(Manager::instance().sipVoIPLink().getEndpoint(), &timer_, &delay) == PJ_SUCCESS) {
             timer_.id = PJ_TRUE;
         }
     }
diff --git a/src/sip/pres_sub_server.cpp b/src/sip/pres_sub_server.cpp
index 27f81e8b793853b21a4f55d00b2d4a7617dac5a6..0e1454c4ab6fe44b75e1c2e390887e0f52ef8cd9 100644
--- a/src/sip/pres_sub_server.cpp
+++ b/src/sip/pres_sub_server.cpp
@@ -131,7 +131,7 @@ PresSubServer::pres_on_rx_subscribe_request(pjsip_rx_data *rdata)
         return PJ_FALSE;
     }
 
-    pjsip_endpoint *endpt = getSIPVoIPLink()->getEndpoint();
+    pjsip_endpoint *endpt = Manager::instance().sipVoIPLink().getEndpoint();
     SIPPresence * pres = sipaccount->getPresence();
     pres->lock();
 
diff --git a/src/sip/sdp.cpp b/src/sip/sdp.cpp
index f14060fc24848f1707c86c6450e550fcdd0d16a9..acfa2bac82bfff54297b2f698cfb9cbd92995901 100644
--- a/src/sip/sdp.cpp
+++ b/src/sip/sdp.cpp
@@ -64,7 +64,7 @@ Sdp::Sdp(const std::string& id)
     , telephoneEventPayload_(101) // same as asterisk
 {
     sip_utils::register_thread();
-    memPool_.reset(pj_pool_create(&getSIPVoIPLink()->getCachingPool()->factory,
+    memPool_.reset(pj_pool_create(&Manager::instance().sipVoIPLink().getCachingPool()->factory,
                                   id.c_str(), POOL_INITIAL_SIZE,
                                   POOL_INCREMENT_SIZE, NULL));
     if (not memPool_)
@@ -338,7 +338,7 @@ Sdp::printSession(const pjmedia_sdp_session *session, const char* header)
     static constexpr size_t BUF_SZ = 4095;
     sip_utils::register_thread();
     std::unique_ptr<pj_pool_t, decltype(pj_pool_release)&> tmpPool_(
-        pj_pool_create(&getSIPVoIPLink()->getCachingPool()->factory, "printSdp", BUF_SZ, BUF_SZ, nullptr),
+        pj_pool_create(&Manager::instance().sipVoIPLink().getCachingPool()->factory, "printSdp", BUF_SZ, BUF_SZ, nullptr),
         pj_pool_release
     );
 
@@ -494,7 +494,7 @@ Sdp::getFilteredSdp(const pjmedia_sdp_session* session, unsigned media_keep, uns
     sip_utils::register_thread();
     static constexpr size_t BUF_SZ = 4096;
     std::unique_ptr<pj_pool_t, decltype(pj_pool_release)&> tmpPool_(
-        pj_pool_create(&getSIPVoIPLink()->getCachingPool()->factory,
+        pj_pool_create(&Manager::instance().sipVoIPLink().getCachingPool()->factory,
                            "tmpSdp", BUF_SZ, BUF_SZ, nullptr),
         pj_pool_release
     );
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index 96798b72c08cfd4df52dd2dad40f658c12103501..6b18bc435a40806960f4531ee497feda0d558eaf 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -202,7 +202,7 @@ SIPAccount::newOutgoingCall(const std::string& toUrl,
 
         // TODO: resolve remote host using SIPVoIPLink::resolveSrvName
         std::shared_ptr<SipTransport> t = isTlsEnabled() ?
-            link_->sipTransportBroker->getTlsTransport(tlsListener_, IpAddr(sip_utils::getHostFromUri(to))) :
+            link_.sipTransportBroker->getTlsTransport(tlsListener_, IpAddr(sip_utils::getHostFromUri(to))) :
             transport_;
         setTransport(t);
         call->setTransport(t);
@@ -362,7 +362,7 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
     if (!CreateClientDialogAndInvite(&pjFrom, &pjContact, &pjTo, nullptr, local_sdp, &dialog, &inv))
         return false;
 
-    inv->mod_data[link_->getModId()] = call.get();
+    inv->mod_data[link_.getModId()] = call.get();
     call->inv.reset(inv);
 
     updateDialogViaSentBy(dialog);
@@ -382,7 +382,7 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
         return false;
     }
 
-    const pjsip_tpselector tp_sel = link_->getTransportSelector(transport->get());
+    const pjsip_tpselector tp_sel = link_.getTransportSelector(transport->get());
     if (pjsip_dlg_set_transport(dialog, &tp_sel) != PJ_SUCCESS) {
         JAMI_ERR("Unable to associate transport for invite session dialog");
         return false;
@@ -747,7 +747,7 @@ void SIPAccount::doRegister1_()
         }
     }
 
-    link_->resolveSrvName(
+    link_.resolveSrvName(
         hostname_,
         tlsEnable_ ? PJSIP_TRANSPORT_TLS : PJSIP_TRANSPORT_UDP,
         [w = weak()](std::vector<IpAddr> host_ips) {
@@ -793,7 +793,7 @@ void SIPAccount::doRegister2_()
         initTlsConfiguration();
 
         if (!tlsListener_) {
-            tlsListener_ = link_->sipTransportBroker->getTlsListener(bindAddress, getTlsSetting());
+            tlsListener_ = link_.sipTransportBroker->getTlsListener(bindAddress, getTlsSetting());
             if (!tlsListener_) {
                 setRegistrationState(RegistrationState::ERROR_GENERIC);
                 JAMI_ERR("Error creating TLS listener.");
@@ -815,7 +815,7 @@ void SIPAccount::doRegister2_()
     if (isIP2IP()) {
         // If we use Tls for IP2IP, transports will be created on connection.
         if (!tlsEnable_){
-            setTransport(link_->sipTransportBroker->getUdpTransport(bindAddress));
+            setTransport(link_.sipTransportBroker->getUdpTransport(bindAddress));
         }
         setRegistrationState(RegistrationState::REGISTERED);
         return;
@@ -825,9 +825,9 @@ void SIPAccount::doRegister2_()
         JAMI_WARN("Creating transport");
         transport_.reset();
         if (isTlsEnabled()) {
-            setTransport(link_->sipTransportBroker->getTlsTransport(tlsListener_, hostIp_, tlsServerName_.empty() ? hostname_ : tlsServerName_));
+            setTransport(link_.sipTransportBroker->getTlsTransport(tlsListener_, hostIp_, tlsServerName_.empty() ? hostname_ : tlsServerName_));
         } else {
-            setTransport(link_->sipTransportBroker->getUdpTransport(bindAddress));
+            setTransport(link_.sipTransportBroker->getUdpTransport(bindAddress));
         }
         if (!transport_)
             throw VoipLinkException("Can't create transport");
@@ -914,7 +914,7 @@ void SIPAccount::startKeepAliveTimer()
 
     keepAliveTimerActive_ = true;
 
-    link_->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
+    link_.registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
 }
 
 void SIPAccount::stopKeepAliveTimer()
@@ -922,7 +922,7 @@ void SIPAccount::stopKeepAliveTimer()
     if (keepAliveTimerActive_) {
         JAMI_DBG("Stop keep alive timer %d for account %s", keepAliveTimer_.id, getAccountID().c_str());
         keepAliveTimerActive_ = false;
-        link_->cancelKeepAliveTimer(keepAliveTimer_);
+        link_.cancelKeepAliveTimer(keepAliveTimer_);
     }
 }
 
@@ -938,7 +938,7 @@ SIPAccount::sendRegister()
     setRegistrationState(RegistrationState::TRYING);
 
     pjsip_regc *regc = nullptr;
-    if (pjsip_regc_create(link_->getEndpoint(), (void *) this, &registration_cb, &regc) != PJ_SUCCESS)
+    if (pjsip_regc_create(link_.getEndpoint(), (void *) this, &registration_cb, &regc) != PJ_SUCCESS)
         throw VoipLinkException("UserAgent: Unable to create regc structure.");
 
     std::string srvUri(getServerUri());
@@ -977,7 +977,7 @@ SIPAccount::sendRegister()
     }
 
     if (hasServiceRoute())
-        pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(getServiceRoute(), link_->getPool()));
+        pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(getServiceRoute(), link_.getPool()));
 
     pjsip_regc_set_credentials(regc, getCredentialCount(), getCredInfo());
 
@@ -987,7 +987,7 @@ SIPAccount::sendRegister()
     auto pJuseragent = CONST_PJ_STR(useragent);
     constexpr pj_str_t STR_USER_AGENT = CONST_PJ_STR("User-Agent");
 
-    pjsip_generic_string_hdr *h = pjsip_generic_string_hdr_create(link_->getPool(), &STR_USER_AGENT, &pJuseragent);
+    pjsip_generic_string_hdr *h = pjsip_generic_string_hdr_create(link_.getPool(), &STR_USER_AGENT, &pJuseragent);
     pj_list_push_back(&hdr_list, (pjsip_hdr*) h);
     pjsip_regc_add_headers(regc, &hdr_list);
 
@@ -1068,12 +1068,12 @@ SIPAccount::onRegister(pjsip_regc_cbparam *param)
              */
             // update_rfc5626_status(acc, param->rdata);
 
-            if (checkNATAddress(param, link_->getPool()))
+            if (checkNATAddress(param, link_.getPool()))
                 JAMI_WARN("Contact overwritten");
 
             /* TODO Check and update Service-Route header */
             if (hasServiceRoute())
-                pjsip_regc_set_route_set(param->regc, sip_utils::createRouteSet(getServiceRoute(), link_->getPool()));
+                pjsip_regc_set_route_set(param->regc, sip_utils::createRouteSet(getServiceRoute(), link_.getPool()));
 
             // start the periodic registration request based on Expire header
             // account determines itself if a keep alive is required
@@ -1402,7 +1402,7 @@ SIPAccount::getContactHeader(pjsip_transport* t)
     std::string address;
     pj_uint16_t port;
 
-    link_->findLocalAddressFromTransport(
+    link_.findLocalAddressFromTransport(
         t,
         transportType,
         hostname_,
@@ -1418,7 +1418,7 @@ SIPAccount::getContactHeader(pjsip_transport* t)
         port = publishedPort_;
         JAMI_DBG("Using published address %s and port %d", address.c_str(), port);
     } else if (stunEnabled_) {
-        auto success = link_->findLocalAddressFromSTUN(t, &stunServerName_,
+        auto success = link_.findLocalAddressFromSTUN(t, &stunServerName_,
                                                        stunPort_, address, port);
         if (not success)
             emitSignal<DRing::ConfigurationSignal::StunStatusFailed>(getAccountID());
@@ -1467,7 +1467,7 @@ SIPAccount::getHostPortFromSTUN(pj_pool_t *pool)
 {
     std::string addr;
     pj_uint16_t port;
-    auto success = link_->findLocalAddressFromSTUN(
+    auto success = link_.findLocalAddressFromSTUN(
         transport_ ? transport_->get() : nullptr, &stunServerName_, stunPort_,
         addr, port);
     if (not success)
@@ -1955,7 +1955,7 @@ SIPAccount::scheduleReregistration()
     /* Cancel any re-registration timer */
     if (auto_rereg_.timer.id) {
         auto_rereg_.timer.id = PJ_FALSE;
-        pjsip_endpt_cancel_timer(link_->getEndpoint(), &auto_rereg_.timer);
+        pjsip_endpt_cancel_timer(link_.getEndpoint(), &auto_rereg_.timer);
     }
 
     /* Update re-registration flag */
@@ -1984,7 +1984,7 @@ SIPAccount::scheduleReregistration()
 
     JAMI_WARN("Scheduling re-registration retry in %ld seconds..", delay.sec);
     auto_rereg_.timer.id = PJ_TRUE;
-    if (pjsip_endpt_schedule_timer(link_->getEndpoint(), &auto_rereg_.timer, &delay) != PJ_SUCCESS)
+    if (pjsip_endpt_schedule_timer(link_.getEndpoint(), &auto_rereg_.timer, &delay) != PJ_SUCCESS)
         auto_rereg_.timer.id = PJ_FALSE;
 }
 
@@ -2032,7 +2032,7 @@ SIPAccount::sendTextMessage(const std::string& to, const std::map<std::string, s
 
     /* Create request. */
     pjsip_tx_data *tdata;
-    pj_status_t status = pjsip_endpt_create_request(link_->getEndpoint(), &msg_method,
+    pj_status_t status = pjsip_endpt_create_request(link_.getEndpoint(), &msg_method,
                                                     &pjTo, &pjFrom, &pjTo, nullptr, nullptr, -1,
                                                     nullptr, &tdata);
     if (status != PJ_SUCCESS) {
@@ -2072,7 +2072,7 @@ SIPAccount::sendTextMessage(const std::string& to, const std::map<std::string, s
     /* Initialize Auth header. */
     auto cred = getCredInfo();
     const_cast<pjsip_cred_info*>(cred)->realm = CONST_PJ_STR(hostname_);
-    status = pjsip_auth_clt_init(t->auth_sess.get(), link_->getEndpoint(), tdata->pool, 0);
+    status = pjsip_auth_clt_init(t->auth_sess.get(), link_.getEndpoint(), tdata->pool, 0);
 
     if (status != PJ_SUCCESS) {
         JAMI_ERR("Unable to initialize auth session: %s", sip_utils::sip_strerror(status).c_str());
@@ -2100,7 +2100,7 @@ SIPAccount::sendTextMessage(const std::string& to, const std::map<std::string, s
     im::fillPJSIPMessageBody(*tdata, payloads);
 
     // Send message request with callback SendMessageOnComplete
-    status = pjsip_endpt_send_request(link_->getEndpoint(), tdata, -1, t.release(), &onComplete);
+    status = pjsip_endpt_send_request(link_.getEndpoint(), tdata, -1, t.release(), &onComplete);
 
     if (status != PJ_SUCCESS) {
         JAMI_ERR("Unable to send request: %s", sip_utils::sip_strerror(status).c_str());
@@ -2139,7 +2139,7 @@ SIPAccount::onComplete(void *token, pjsip_event *event)
             cseq_hdr->cseq += 1;
 
             // Resend request
-            status = pjsip_endpt_send_request(acc->link_->getEndpoint(), new_request, -1, c.release(), &onComplete);
+            status = pjsip_endpt_send_request(acc->link_.getEndpoint(), new_request, -1, c.release(), &onComplete);
 
             if (status != PJ_SUCCESS) {
                 JAMI_ERR("Unable to send request: %s", sip_utils::sip_strerror(status).c_str());
diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp
index f3a5052998c10ae35fd6eff1b8c4cbc570898aca..3be80e0c77c57fa7c7bf8c0211c853c4fa904825 100644
--- a/src/sip/sipaccountbase.cpp
+++ b/src/sip/sipaccountbase.cpp
@@ -58,7 +58,7 @@ static constexpr std::chrono::steady_clock::duration COMPOSING_TIMEOUT {std::chr
 SIPAccountBase::SIPAccountBase(const std::string& accountID)
     : Account(accountID),
     messageEngine_(*this, fileutils::get_cache_dir()+DIR_SEPARATOR_STR+getAccountID()+DIR_SEPARATOR_STR "messages"),
-    link_(getSIPVoIPLink())
+    link_(Manager::instance().sipVoIPLink())
 {}
 
 SIPAccountBase::~SIPAccountBase() {}
diff --git a/src/sip/sipaccountbase.h b/src/sip/sipaccountbase.h
index f72651d05403fd765ee308389e110bf18edfd1fc..14e3b794d9a2ae5c9d3fbdb531b3323b039ceb67 100644
--- a/src/sip/sipaccountbase.h
+++ b/src/sip/sipaccountbase.h
@@ -342,7 +342,7 @@ protected:
     /**
      * Voice over IP Link contains a listener thread and calls
      */
-    std::shared_ptr<SIPVoIPLink> link_;
+    SIPVoIPLink& link_;
 
     /**
      * interface name on which this account is bound
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index 238189e7187c5959df6c55b541c91c56e4659ac0..4732252d0a106a0a503efcea511ca985dd086ca8 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -267,7 +267,7 @@ SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
     if (tdata->msg->body == NULL)
         pjsip_tx_data_dec_ref(tdata);
     else
-        pjsip_dlg_send_request(inv->dlg, tdata, getSIPVoIPLink()->getModId(), NULL);
+        pjsip_dlg_send_request(inv->dlg, tdata, Manager::instance().sipVoIPLink().getModId(), NULL);
 }
 
 void
@@ -335,7 +335,7 @@ SIPCall::answer()
         JAMI_WARN("[call:%s] Negotiator is NULL, we've received an INVITE without an SDP",
                   getCallId().c_str());
         pjmedia_sdp_session *dummy = 0;
-        getSIPVoIPLink()->createSDPOffer(inv.get(), &dummy);
+        Manager::instance().sipVoIPLink().createSDPOffer(inv.get(), &dummy);
 
         if (account.isStunEnabled())
             updateSDPFromSTUN();
@@ -416,13 +416,7 @@ SIPCall::refuse()
 static void
 transfer_client_cb(pjsip_evsub *sub, pjsip_event *event)
 {
-    auto link = getSIPVoIPLink();
-    if (not link) {
-        JAMI_ERR("no more VoIP link");
-        return;
-    }
-
-    auto mod_ua_id = link->getModId();
+    auto mod_ua_id = Manager::instance().sipVoIPLink().getModId();
 
     switch (pjsip_evsub_get_state(sub)) {
         case PJSIP_EVSUB_STATE_ACCEPTED:
@@ -513,7 +507,7 @@ SIPCall::transferCommon(const pj_str_t *dst)
      * because after this function, we can no find the cooresponding
      * voiplink from the call any more. But the voiplink is useful!
      */
-    pjsip_evsub_set_mod_data(sub, getSIPVoIPLink()->getModId(), this);
+    pjsip_evsub_set_mod_data(sub, Manager::instance().sipVoIPLink().getModId(), this);
 
     /*
      * Create REFER request.
@@ -1372,7 +1366,7 @@ SIPCall::InvSessionDeleter::operator ()(pjsip_inv_session* inv) const noexcept
     // prevent this from getting accessed in callbacks
     // JAMI_WARN: this is not thread-safe!
     if (!inv) return;
-    inv->mod_data[getSIPVoIPLink()->getModId()] = nullptr;
+    inv->mod_data[Manager::instance().sipVoIPLink().getModId()] = nullptr;
     // NOTE: the counter is incremented by sipvoiplink (transaction_request_cb)
     pjsip_inv_dec_ref(inv);
 }
@@ -1401,7 +1395,7 @@ SIPCall::merge(Call& call)
     std::lock_guard<std::recursive_mutex> lk1 {callMutex_, std::adopt_lock};
     std::lock_guard<std::recursive_mutex> lk2 {subcall.callMutex_, std::adopt_lock};
     inv = std::move(subcall.inv);
-    inv->mod_data[getSIPVoIPLink()->getModId()] = this;
+    inv->mod_data[Manager::instance().sipVoIPLink().getModId()] = this;
     setTransport(std::move(subcall.transport_));
     sdp_ = std::move(subcall.sdp_);
     peerHolding_ = subcall.peerHolding_;
diff --git a/src/sip/sippresence.cpp b/src/sip/sippresence.cpp
index b1a04e98c4170bff6c65fcc4ae7364a59212c2a5..5078c5dc5eda92a6cb6668d1ad19a42e9e33b4a2 100644
--- a/src/sip/sippresence.cpp
+++ b/src/sip/sippresence.cpp
@@ -93,7 +93,7 @@ pjsip_pres_status * SIPPresence::getStatus()
 
 int SIPPresence::getModId() const
 {
-    return getSIPVoIPLink()->getModId();
+    return Manager::instance().sipVoIPLink().getModId();
 }
 
 pj_pool_t*  SIPPresence::getPool() const
@@ -481,7 +481,7 @@ SIPPresence::publish(SIPPresence *pres)
     pj_status_t status;
     constexpr pj_str_t STR_PRESENCE = CONST_PJ_STR("presence");
     SIPAccount * acc = pres->getAccount();
-    pjsip_endpoint *endpt = getSIPVoIPLink()->getEndpoint();
+    pjsip_endpoint *endpt = Manager::instance().sipVoIPLink().getEndpoint();
 
     /* Create and init client publication session */
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index 951a652bde476f289ff2592334b734d0a2984ead..357b87487f32dc7f6a4cacfd59c709e58b57b1df 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -82,8 +82,6 @@ static void outgoing_request_forked_cb(pjsip_inv_session *inv, pjsip_event *e);
 static void transaction_state_changed_cb(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e);
 static std::shared_ptr<SIPCall> getCallFromInvite(pjsip_inv_session* inv);
 
-decltype(getGlobalInstance<SIPVoIPLink>)& getSIPVoIPLink = getGlobalInstance<SIPVoIPLink>;
-
 static void
 handleIncomingOptions(pjsip_rx_data *rdata)
 {
@@ -204,13 +202,7 @@ transaction_request_cb(pjsip_rx_data *rdata)
     if (not remote_user.empty() and not remote_hostname.empty())
         peerNumber = remote_user + "@" + remote_hostname;
 
-    auto link = getSIPVoIPLink();
-    if (not link) {
-        JAMI_ERR("no more VoIP link");
-        return PJ_FALSE;
-    }
-
-    auto account(link->guessAccount(toUsername, viaHostname, remote_hostname));
+    auto account(Manager::instance().sipVoIPLink().guessAccount(toUsername, viaHostname, remote_hostname));
     if (!account) {
         JAMI_ERR("NULL account");
         return PJ_FALSE;
@@ -314,7 +306,7 @@ transaction_request_cb(pjsip_rx_data *rdata)
         }
     }
 
-    auto transport = link->sipTransportBroker->addTransport(rdata->tp_info.transport);
+    auto transport = Manager::instance().sipVoIPLink().sipTransportBroker->addTransport(rdata->tp_info.transport);
     auto call = account->newIncomingCall(remote_user, {{"AUDIO_ONLY", (hasVideo ? "false" : "true") }}, transport);
     if (!call) {
         return PJ_FALSE;
@@ -487,16 +479,10 @@ static void
 tp_state_callback(pjsip_transport* tp, pjsip_transport_state state,
                   const pjsip_transport_state_info* info)
 {
-    // There is no way (at writing) to link a user data to a PJSIP transport.
-    // So we obtain it from the global SIPVoIPLink instance that owns it.
-    // Be sure the broker's owner is not deleted during process
-    if (auto sipLink = getSIPVoIPLink()) {
-        if (auto& broker = sipLink->sipTransportBroker)
-            broker->transportStateChanged(tp, state, info);
-        else
-            JAMI_ERR("SIPVoIPLink with invalid SipTransportBroker");
-    } else
-        JAMI_ERR("no more VoIP link");
+    if (auto& broker = Manager::instance().sipVoIPLink().sipTransportBroker)
+        broker->transportStateChanged(tp, state, info);
+    else
+        JAMI_ERR("SIPVoIPLink with invalid SipTransportBroker");
 }
 
 /*************************************************************************************************/
diff --git a/src/sip/sipvoiplink.h b/src/sip/sipvoiplink.h
index 91e25e675c21c84910836e3ea439aa1c2d3ca9ae..3664bb527c91a01886173a6d9dcec5ff2b83fe7c 100644
--- a/src/sip/sipvoiplink.h
+++ b/src/sip/sipvoiplink.h
@@ -58,13 +58,9 @@ class SipTransportBroker;
 
 typedef std::map<std::string, std::shared_ptr<SIPCall> > SipCallMap;
 
-extern decltype(getGlobalInstance<SIPVoIPLink>)& getSIPVoIPLink;
-
 /**
  * @file sipvoiplink.h
  * @brief Specific VoIPLink for SIP (SIP core for incoming and outgoing events).
- *          This class is based on the singleton design pattern.
- *          One SIPVoIPLink can handle multiple SIP accounts, but all the SIP accounts have all the same SIPVoIPLink
  */
 
 class SIPVoIPLink {