Setup guide

Run nearby search with PostGIS

Use geography points and GiST indexes for practical nearby search inside Postgres.

The Goal

Build a nearby search that is easy to explain.

For most products, that means: store a point, index it, search within a radius, then sort by distance.

Create The Table

create extension if not exists postgis;

create table places (
  id bigserial primary key,
  account_id bigint not null,
  name text not null,
  location geography(point, 4326) not null,
  is_active boolean not null default true
);

create index places_location_gix
  on places using gist (location);

Use geography(point, 4326) when you are storing longitude and latitude and want distances in meters.

Insert A Point

st_makepoint takes longitude first, then latitude.

insert into places (account_id, name, location)
values (
  1,
  'Empire State Building',
  st_makepoint(-73.9857, 40.7484)::geography
);

That longitude-first order is easy to get wrong.

Query Nearby Places

select
  id,
  name,
  st_distance(
    location,
    st_makepoint(-73.9857, 40.7484)::geography
  ) as meters_away
from places
where account_id = 1
  and is_active
  and st_dwithin(
    location,
    st_makepoint(-73.9857, 40.7484)::geography,
    2000
  )
order by meters_away
limit 20;

The radius is explicit: 2000 meters.

Product Decisions

Do not let the database decide what nearby means.

Pick the product rule:

Once the rule is clear, the SQL is easier to write and test.

Common Mistakes

When To Move On

PostGIS can take you far. Move beyond this setup when you need routing, tile generation, heavy GIS processing, or a map stack owned by a separate team.

For nearby search in an app, keep it in Postgres until there is a real reason not to.

References