ST_Buffer(geography, ...) uses a fixed projection guess with
_ST_BestSRID, which are typically UTM zones or whatever makes sense to the algorithm. This is why you see the differences, because they are different projections that are not optimized for the location of the points.
For simple point buffers, you could use a custom azimuthal equidistant projection, which are better suited for unique points around the globe.
For PostGIS 2.2 and earlier, get a new ST_Transform function to use custom projections:
CREATE FUNCTION ST_Transform(geom geometry, from_proj text, to_srid integer)
RETURNS geometry AS
'SELECT postgis_transform_geometry(ST_SetSRID($1, 99), $2, proj4text, $3)
FROM spatial_ref_sys WHERE srid=$3;'
LANGUAGE sql IMMUTABLE STRICT;
And use it to determine buffers of various places:
ST_Transform(ST_Buffer(ST_MakePoint(0, 0), 100000.0),
concat('+proj=aeqd +lat_0=', ST_Y(ST_Centroid(geom)),
' +lon_0=', ST_X(ST_Centroid(geom)),
' +x_0=0 +y_0=0 +ellps=WGS84 +no_defs '),
4326)::geography) / 1000000 AS area_km2
SELECT 'SRID=4326;POINT(0 0)'::geometry geom
UNION SELECT 'SRID=4326;POINT(30 30)'::geometry
I hope a 0.002 km² difference is acceptable. You can also experiment with Lambert azimuthal equal-area projections by using
+proj=laea for the PROJ text; I get differences as low as 0.00007 km².