Thanks to Paul Norman’s reminder in a previous post, we now have all the pieces we need to complete an ST_Buffer function that exposes all the wonderful goodness of buffer style parameters to geography users and also chooses the best local coordinate system automatically.
We use _ST_BestSRID to choose our local coordinate system.
Remember my previous three disadvantages:
- It didn’t do this at a low enough level to automatically use the best available local coordinate system. This leaves it to the user to choose the best available local coordinate system
- It used a different function name than you otherwise use for buffering.
- Finally, it wouldn’t let you use all the other parameters that ST_Buffer exposes through the use of buffer style parameters.
They are now all solved.
CREATE OR REPLACE FUNCTION ST_Buffer(g1 geography, radius_of_buffer float, num_seg_quarter_circle integer) RETURNS geography AS $BODY$ WITH transformed AS ( SELECT ST_Transform(g1::geometry, _ST_BestSRID(g1)) AS geom ), buffered AS ( SELECT ST_Buffer(geom, radius_of_buffer, num_seg_quarter_circle) AS geom FROM transformed ), transformed_4326 AS ( SELECT ST_Transform(geom, 4326) AS geom FROM buffered ) SELECT geom::geography FROM transformed_4326 $BODY$ LANGUAGE sql VOLATILE;
CREATE OR REPLACE FUNCTION ST_Buffer(g1 geography, radius_of_buffer float, buffer_style_parameters text) RETURNS geography AS $BODY$ WITH transformed AS ( SELECT ST_Transform(g1::geometry, _ST_BestSRID(g1)) AS geom ), buffered AS ( SELECT ST_Buffer(geom, radius_of_buffer, buffer_style_parameters) AS geom FROM transformed ), transformed_4326 AS ( SELECT ST_Transform(geom, 4326) AS geom FROM buffered ) SELECT geom::geography FROM transformed_4326 $BODY$ LANGUAGE sql VOLATILE;
Let’s try this!
SELECT ST_Buffer( ST_GeomFromText( 'LINESTRING(5 2.5,0 -2.50,-5 2.5)' )::geography, 500000, 'join=mitre');

Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
(poor editing earlier tonight. My apologies.
This is nice but still fails in one important aspect – it will create significant inaccuracies once your buffering distance reaches values where buffering in a single local coordinate system is getting problematic which, depending on your precision requirements, will likely happen at distances of a few degrees. A solution to this would require either an iterative split and merge technique of a completely different approach on a very basic level (i.e. attempting truly spherical buffering).
Very true. I forgot about this contigency. Hopefully, this is a better solution: https://smathermather.wordpress.com/2016/01/12/st_buffer-on-geography-iteration/