Whether using vincenty or haversine or the spherical law of cosines, there is wisdom in becoming aware of any potential issues with the code you are planning to use, things to watch out for and mitigate, and how one deals with vincenty vs haversine vs sloc issues will differ as one becomes aware of each one's lurking issues/edgecases, which may or may not be popularly known. The seasoned programmer knows this. Newbies may not. I hope to spare some of them frustration when a snippet from a forum does something unexpected, in certain cases. If one is seriously going to use some version of any of these, vincenty, haversine, sloc, then SE, SO, Reddit, Quora, etc, may have provided limited help in some initial coding of a solution, but that does not mean that their solution or accepted 'answer' is free of issues. If a project is important enough, it deserves an appropriate reasonable amount of research. Read the manual, read the docs, and if a code review of that code exists, read that. Copying and pasting a snippet or gist that was upvoted a hundred or more times does not mean its safety is comprehensive and assured.
The intriguing answer posted by cffk raises the point of being aware of lurking edgecases, in packaged solutions, that can produce exceptions or other difficulties. The specific claims made in that post are beyond my time budget to pursue at present, but I take away from it that there are indeed lurking issues in certain packages, including at least one vincenty implementation, regarding which at least one person has proposed to improve one way or another, in order to minimize or eliminate the risk of encountering those difficulties. I won't add further to that topic concerning vincenty (being far too ignorant of it), but will turn instead to haversine, at least partly on topic with the OP.
The popularly published haversine formula, whether in python or another language, because it is going to be most likely using the IEEE 754 floating point spec on most all intel and intel-like systems today, and ARM processors, powerPC, etc, it is going to also be susceptible to rare but real and repeatable exception errors very near or at 180 degree arc distance, antipodal points, due to floating point approximations and rounding. Some newbies may not yet have been bitten by this situation. Because this fp spec approximates and rounds, this doesn't mean that any code that calls on fp64 might cause exception errors, no. But some code, some formulas might have not so obvious edgecases where the approximations and roundings of IEEE 754 fp64 may cause a value to stray slightly out of the domain of a math method that is expected to flawlessly evaluate such a value. An example... sqrt(). If a negative value finds its way into a sqrt(), such as sqrt(-0.00000000000000000122739), there will be an exception error. In the haversine formula, the manner in which it progresses towards a solution, there are two sqrt() methods in the atan2(). The a that is calculated and then used in the sqrt(), can, at the antipodal points on the globe, slightly stray below 0.0 or above 1.0, very slightly because of fp64 approximations and rounding, rarely, but repeatably. Consistent reliable repeatability, in this context, makes this an exception risk, an edgecase to protect, to mitigate, rather than an isolated random fluke. Here's an example of a short python3 snippet of haversine, without the necessary protection:
import math as m
a = m.sin(dlat / 2)**2 + m.cos(lat1) * m.cos(lat2) * m.sin(dlon / 2)**2
c = 2 * m.atan2(m.sqrt(a), m.sqrt(1 - a))
distance = Radius * c
Very near or at antipodal points, a calculated in the first line of the formula may stray negative, rarely, but repeatably with those same lat lon coordinates. To protect/correct those rare occurrences, one can simply add, after the a calculation,as seen below:
import math as m
note = ''
a = m.sin(dlat / 2)**2 + m.cos(lat1) * m.cos(lat2) * m.sin(dlon / 2)**2
if a < 0.0: a = 0.0 ; note = '*'
if a > 1.0: a = 1.0 ; note = '**'
c = 2 * m.atan2(m.sqrt(a), m.sqrt(1 - a))
distance = Radius * c
# note = '*' # a went below 0.0 and was normalized back to 0.0
# note = '**' # a went above 1.0 and was normalized back to max of 1.0
Of course I did not show the entire function here, but a short snippet as is so often posted. But this one shows the protection for the sqrt(), by testing the a, and normalizing it if necessary, also saving the need to put the whole thing in a try except. The note = '' up top is to prevent the bytecode stage from protesting that note is being used before being assigned a value, if it is returned with the result of the function.
With this simple change, of adding the two a tests, the sqrt() functions will be happy, and the code now has an additional note that can be returned to calling code, to alert that a result has been slightly normalized, and why. Some may care, some may not, but its there, preventing an exception error, that 'can' otherwise occur. A try except block may catch the exception, but not fix it, unless explicitly written to do so. It seems easier to code the correction line(s) immediately after the a calculation line. Thoroughly scrubbed input should then not require a try except block here at all.
Summary, if using haversine, coded explicitly rather than using a package or library, no matter your language of choice, it would be a good idea to test and to normalize a back into the needful range of 0.0 <= a <= 1.0 in order to protect the next line with its c calculations. But the majority of haversine code snippets do not show it, and do not mention the risk.
Experience: during thorough testing around the globe, in 0.001 degree increments, I've filled up a hard drive with lat lon combinations that caused an exception, a reliable consistent repeatable exception, during a month of also collaterally testing the reliability of the CPU cooling fan, and my patience. Yes, I've since deleted most of those logs, since their purpose was mostly to prove the point (if the pun is allowed). But I have some shorter logs of 'problem lat lon values', kept for testing purposes.
Accuracy: Will a and the entire haversine result lose some accuracy by normalizing it that small bit back into domain? Not much, maybe no more than the fp64 approximations and roundings were already introducing, that caused that slight drift out of domain. If you have found haversine acceptable over vincenty already -- simpler, faster, easier to customize, troubleshoot and maintain, then haversine may be a good solution for your project.
I've used haversine on an overhead projected skysphere for measuring angular distances between objects in the sky, as viewed from a position on earth, mapping azimuth and alt to skysphere lat lon equivalent-like coordinates, no elipsoid to consider at all, since the projected theoretical skysphere is a perfect sphere, when it comes to measuring angular distance look angles between two objects from a position on the earth's surface. It suits my needs perfectly. So, haversine still is very useful, and very accurate, in certain applications (well within my purposes) ... but if you do use it, whether on the earth for GIS or navigation, or in sky object observations and measurements, do protect it in the case of antipodal points or very near antipodal points, by testing a and nudging it back into its needful domain when needed.
The unprotected haversine is all over the internet, and I've only seen one old usenet post that showed some protection, I think from someone at JPL, and that may have been pre-1985, pre- IEEE 754 floating point spec. Two other pages mentioned possible issues near antipodal points, but did not describe those issues, or how one might mitigate them. So there is concern for the newbies (like me) who may not always understand good practice well enough to further research, and test edgecases, of some code they have copied and pasted into a project in trust. cffk's intriguing post was refreshing in that it was public with these types of issues, that are not often mentioned, rarely publicly coded for protection in snippets, and rarely discussed in this way, compared to the amount of unprotected and undiscussed versions that are posted.
As of 20190923, the wiki page for haversine formula does indeed mention the problem possible at antipodal points, due to floating point issues in computing devices ... encouraging ...
https://en.wikipedia.org/wiki/Haversine_formula
(because that wiki page does not, at this time, have an html anchor for the section to which I would directly link, therefore, after the page loads, do a search on that browser page for 'When using these formulae' and you will see the haversine's problem with antipodal points mentioned, more officially.)
And this other site also has a very brief mention of it:
https://www.movable-type.co.uk/scripts/latlong.html
If one does a find on that page for 'including protection against rounding errors', there is this...
If atan2 is not available, c could be calculated from 2 ⋅ asin( min(1, √a) ) (including protection against rounding errors).
Now there is a rare instance where rounding errors are mentioned, and protection shown for the asin() version, yet not mentioned or shown for the atan2() version. But at least the risk of rounding errors are mentioned.
imho, any 24/7/365 application using haversine, needs this protection near the antipodal points as an important and simple detail.
I don't know which haversine packages do or do not include this protection, but if you are new to all this, and you are going to use the popularly published 'snippet' version(s), now you know it needs protection, and that protection is very simple to implement, that is, if you are not using vincenty, and not using a packaged haversine without easy access to modify the code of the package.
IOW, whether using vincenty or haversine or sloc, one ought to become aware of any issues with the code, things to watch out for and mitigate, and how one deals with vincenty vs haversine vs sloc issues will differ as one becomes aware of each one's lurking issues/edgecases, which may or may not be popularly known.