← companymap.co.uk How it works

How it works

Putting all 6.4 million UK companies on one map

Every company on the UK register, on one interactive map in the browser. No sign-up, nothing to install. This is how the live platform works: where the data comes from, how it renders a million points without slowing down, and why a traffic spike can't take it offline.

By Optional Ltd · 24 June 2026 · companymap.co.uk

Companies House publishes the entire UK company register for free, but it ships as a single CSV of around 2.6 GB. That format is fine for querying and close to useless for seeing the data: where companies actually are, which towns and streets they cluster in, what an industrial estate looks like with every business on it plotted as a point.

Company Map turns that register into one interactive map. The whole country loads at once, every street can be zoomed into, and the companies in any area can be exported as a structured list.

What follows covers the platform as it runs today: the live map and the export behind it, how six and a half million companies are rendered in a browser, and how the system is hosted to stay fast under load. The focus is the live product, not the roadmap.

6.4Mcompanies on the register
1.0Mdistinct map locations
97.2%geocoded to a point

From register to map points

The data is straightforward to obtain and harder to use well. Companies House provides the full register under the Open Government Licence and refreshes it monthly. That cadence matters: the register grows by sixty to eighty thousand companies a month, so a stale copy drifts from reality quickly, and Company Map re-imports on the same monthly cycle.

Each company carries a registered-office address, which is geocoded to a latitude and longitude. Around 97% resolve to a precise point. The remainder have addresses too imprecise to place reliably, and are left off the map rather than positioned by guesswork.

Aggregation is what makes the map viable. Companies are not evenly distributed; they concentrate at shared addresses, where a single formation agent or accountancy office can be the registered office for thousands of companies at once. Grouping the register by coordinate collapses six and a half million companies into roughly one million distinct locations, each carrying a company count. A location in central London can represent 40,000 companies; one in a village, a single business.

Drawing the map without drawing a million dots

Every location is loaded into the browser once and held in memory. MapLibre GL JS provides the base map (CARTO Positron in light mode, Dark Matter in dark), and deck.gl draws the company points over it as a single ScatterplotLayer. Because deck.gl renders on the GPU rather than creating a DOM node per point, the map stays smooth at 60 frames a second while panning across the whole dataset.

Drawing all million points at once would serve no purpose: a display is only a couple of thousand pixels wide, and a million overlapping dots would render as a solid mass. Instead, after each pan or zoom settles (debounced by 300 ms to avoid recomputing mid-gesture), the points inside the current view are selected and capped at 25,000 markers. Fully zoomed out, those 25,000 stand in for the complete set. Zoomed in, far fewer points fall in view, the cap no longer applies, and every location in the area is shown. Marker size scales with zoom, from fine specks at country level to clear markers with a subtle glow at street level.

The figures on screen stay exact, because the counts are calculated independently of what is drawn. The total and visible-company figures sum across the full dataset, and the full set in view, not the 25,000-marker subset on the GPU. The map can therefore show 25,000 points while accurately reporting, say, 1.2 million companies in frame.

Getting the data to the browser

The dataset is delivered as a single static file. Every aggregated location is baked into one locations.json, downloaded once when the page loads. From that point, panning, zooming and the live counts all run client-side, with no further requests to a server.

Uncompressed, that file is about 62 MB. Gzip reduces it to roughly 15 MB, which is what is served, with Content-Encoding: gzip. Compression is applied at deploy time rather than by the CDN, because CloudFront only auto-compresses objects up to 10 MB and this file exceeds that. A loading screen shows facts drawn from the data while the file streams in, and a version flag lets returning visitors skip the load once the file is cached.

Hosting that absorbs traffic spikes

Almost everything the site serves is static: the page, the JavaScript and the location dataset. All of it is hosted on S3 behind CloudFront, so a sudden surge of visitors, such as from a widely shared link, is absorbed by the CDN rather than any single server.

Only genuinely dynamic work runs on a server: checkout, the export and location search. These are handled by a small Flask application on a single modest EC2 instance, reachable only through CloudFront. Because traffic for anything that can be served as a file never reaches that instance, it can be sized for database work rather than for load. Spikes land on the static layer, by design.

Exporting an area

Viewing the map is free. The export turns a selected area into a structured list of the companies it contains. The bounds of the current view are sent to a PostgreSQL and PostGIS database, a trimmed-down copy of the register of three to four gigabytes kept separate from the rest of the system, which returns the companies inside that box. After payment via Stripe, the CSV is generated server-side, stored in S3 and emailed as a download link; larger exports are produced asynchronously, with a status page that waits for the file to be ready.

The spatial query is tuned to return in well under a second on a two-core instance. A GiST index covers the geometry column; the count runs against the locations table alone (one row per location, avoiding a join); and the matching rows are filtered, sorted and limited to a single page before each company's full address is retrieved with a LATERAL lookup. Without the index, the same query scans the full join and takes around thirty seconds. With it, roughly 0.7.

The payment screen states plainly what the export contains, which keeps expectations accurate. Each row includes the company name, number, status, type, incorporation date, registered address, postcode, SIC industry codes and a direct link to its Companies House record. It does not include phone numbers or email addresses, which the register does not hold. The Companies House link is the route to the rest: directors, filing history and the official correspondence address. The result is a ready-made list of genuine local businesses to qualify and contact, not a pre-populated call list.


Open the map →