Another approach to ST_Buffer would be to subdivide the geometries before buffering, and put them all together at the end. ST_SubDivide can do this for us. We can tell it how may vertices we want in each geometry (minimum of 8). Since _ST_BestSRID will try UTM first, we’ll add enough nodes to ensure we always have 8 nodes within the 1,000,000 meter width of a UTM zone by segmentizing at 62,500 meters.
CREATE OR REPLACE FUNCTION ST_Buffer(g1 geography, radius_of_buffer float, num_seg_quarter_circle integer) RETURNS geography AS $BODY$ WITH subdivided AS ( SELECT CASE WHEN ST_GeometryType(g1::geometry) = 'ST_Point' THEN g1 ELSE (SELECT ST_SubDivide(ST_Segmentize(g1::geometry, 62500), 8) AS geom) END ), transformed_local AS ( SELECT ST_Transform(g1::geometry, _ST_BestSRID(geom)) AS geom FROM subdivided ), buffered AS ( SELECT ST_Buffer(geom, radius_of_buffer, num_seg_quarter_circle) AS geom FROM transformed_local ), transformed_4326 AS ( SELECT (ST_Dump(ST_Transform(geom, 4326))).geom AS geom FROM buffered ), checksrid AS ( SELECT geom FROM transformed_4326 ) SELECT ST_Union(geom)::geography FROM checksrid; $BODY$ LANGUAGE sql VOLATILE;
Aaand, a somewhat unrelated image (just the buffered subdivision of a buffered point, not really an output from our function above. More on all this later.
Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.

Clik here to view.
