FIAS Integration for Address Suggestions on Website
FIAS (Federal Information Address System) — official state registry of Russian addresses. Data distributed freely, updated weekly, used as reference base for address correctness verification. For website address suggestions, FIAS rarely used directly: full database weighs several gigabytes, requires separate infrastructure. In practice, work via DaData or similar services storing and indexing FIAS data, providing convenient API.
However, if task is working with FIAS without intermediaries — e.g., closed contour or internal corporate portal — need to build own infrastructure.
Getting and Loading FIAS Data
Current dumps published at https://fias.nalog.ru/. Two formats available: full base (XML, dozens of archives) and delta updates (weekly). Since 2022 FIAS gradually replaced by GARS, XML format slightly changed, but principles same.
Minimal table set for address suggestions:
-
AS_ADDR_OBJ— regions, districts, cities, streets -
AS_HOUSES— houses, buildings, corps -
AS_HIERARCHY— hierarchical relationships -
AS_ADDR_OBJ_PARAMS— additional parameters (postal code etc)
Loading XML dump to PostgreSQL via php-script or python-parser takes 3–6 hours initially. For subsequent updates use delta files — loading takes 10–30 minutes.
Table Structure and Indexes
CREATE TABLE addr_obj (
id UUID PRIMARY KEY,
object_id BIGINT,
name TEXT NOT NULL,
type_name TEXT,
level SMALLINT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE houses (
id UUID PRIMARY KEY,
object_id BIGINT,
addr_obj_id BIGINT,
house_num TEXT,
build_num TEXT,
struct_num TEXT,
is_active BOOLEAN DEFAULT true
);
-- Index for full-text search
CREATE INDEX idx_addr_obj_name_fts
ON addr_obj USING GIN (to_tsvector('russian', name));
-- Index for hierarchy
CREATE INDEX idx_hierarchy_parent ON hierarchy(parent_obj_id);
CREATE INDEX idx_hierarchy_child ON hierarchy(object_id);
Without GIN index, search across 20+ million records is painfully slow.
API for Suggestions
Simple PHP/Laravel endpoint accepting string, returning variants:
public function suggest(Request $request): JsonResponse
{
$query = trim($request->input('q', ''));
if (mb_strlen($query) < 2) {
return response()->json([]);
}
$results = DB::select("
SELECT
ao.name,
ao.type_name,
ao.level,
h.path_name
FROM addr_obj ao
JOIN addr_hierarchy h ON h.object_id = ao.object_id
WHERE to_tsvector('russian', ao.name) @@ plainto_tsquery('russian', ?)
AND ao.is_active = true
ORDER BY ao.level, ao.name
LIMIT 10
", [$query]);
return response()->json($results);
}
For house input, query slightly more complex — first find street by its object_id, then search houses by addr_obj_id.
Frontend: Suggestions Connection
Browser side — standard debounce + fetch logic:
let timer;
input.addEventListener('input', () => {
clearTimeout(timer);
timer = setTimeout(async () => {
const q = input.value.trim();
if (q.length < 2) return;
const res = await fetch(`/api/fias/suggest?q=${encodeURIComponent(q)}`);
const data = await res.json();
renderDropdown(data);
}, 250);
});
250ms delay avoids request per keystroke.
Own Infrastructure Nuances
Own FIAS base justified when: no possibility to use external services (closed network, security requirements), planning very high request volume (tens of thousands daily), need full search logic customization.
If no such limits — simpler and cheaper to work via DaData. Own infrastructure cost: separate server with 8+ GB RAM, ~50 GB disk space, delta auto-update setup. Initial loading and setup takes 1–2 working days, excluding search quality debugging.







