Philippine Standard Geographic Code (PSGC) Guide
The standard coding system used to classify Philippine administrative divisions, census records, and GIS boundaries.
What is the PSGC?
The Philippine Standard Geographic Code (PSGC) is a systematic classification maintained by the Philippine Statistics Authority (PSA) under Republic Act No. 10625. It provides a unique numeric identifier for every administrative division in the country, from top-level administrative regions down to individual barangays.
In geospatial engineering and public policy analysis, the PSGC serves as the canonical join key connecting tabular datasets, such as Census of Population and Housing (CPH) demographics, health records from the Department of Health, and tax revenues, directly to vector geometries published by NAMRIA and local government units.
PSGC Code Structure: 9-Digit Legacy vs 10-Digit Standard
Spatial datasets in the Philippines currently use two primary numeric lengths. The PSA introduced the 10-digit standard in 2018 to resolve digit exhaustion in rapidly subdividing municipalities. Developers must support both structures when ingesting spatial archives.
13 denotes the National Capital Region (NCR), 03 denotes Central Luzon, 04 denotes CALABARZON, and 19 denotes BARMM.000 or 0000 indicates the record represents the entire city or municipality rather than a specific sub-unit.Philippine Administrative Levels Under Republic Act No. 7160
The local governance hierarchy follows the Local Government Code of 1991 (Republic Act No. 7160). Each level holds defined political powers, taxation authorities, and statutory responsibilities:
1. Administrative Regions (18 Units)
Regional councils coordinate socioeconomic planning and national agency regional offices. The Philippines has 18 administrative regions: 16 administrative groupings, the Bangsamoro Autonomous Region in Muslim Mindanao (BARMM, governed by RA 11054), and the newly reconstituted Negros Island Region (NIR, established by RA 12000).
2. Provinces (82 Units)
There are 82 statutory provinces. Provinces consist of component cities and municipalities. Provincial governments oversee health facilities, provincial road networks, and inter-municipal zoning. Provinces do not hold statutory jurisdiction over Highly Urbanized Cities located inside their geographic boundaries.
3. Cities and Municipalities (1,634 Units)
Cities and municipalities serve as primary tax collection and business permitting units. Cities are grouped into 3 legal classes: 33 Highly Urbanized Cities (HUCs) with minimum populations of 200,000 and annual income of 50 million pesos (1991 base); 5 Independent Component Cities (ICCs) whose charters forbid voting for provincial officials; and 111 Component Cities under provincial supervision.
4. Barangays (42,000+ Units)
The grassroots political unit. Barangays manage community disputes through the Katarungang Pambarangay system under RA 7160 Sections 399 to 422, collect local clearance fees, and maintain primary neighborhood roads and drainage conduits.
Critical Boundary Cases: NIR, BARMM SGA, and Supreme Court Rulings
GIS pipelines frequently break when using outdated reference tables. Developers must account for three significant administrative boundary updates:
Negros Island Region (RA 12000, June 2024)
Signed into law on June 11, 2024, Republic Act No. 12000 unified Negros Occidental (transferred from Region VI, Western Visayas), Negros Oriental (transferred from Region VII, Central Visayas), and Siquijor (transferred from Region VII) into Region XVIII. Spatial queries aggregating statistics by region must reflect this realignment rather than relying on legacy Region VI or VII definitions.
BARMM Special Geographic Area (BAA Nos. 41 to 48, 2024)
Following the 2019 plebiscite where 63 barangays in North Cotabato voted to join BARMM, the Bangsamoro Transition Authority passed Bangsamoro Autonomy Act Nos. 41 through 48. In April 2024, voters ratified the creation of 8 new municipalities: Pahamudin, Kadayangan, Nabalawag, Tugunan, Ligawasan, Malidegao, Datu Benito, and Old Kaabakan. These units are coded under PSGC regional prefix 19 and geographic cluster 19099, separating them from Region XII (SOCCSKSARGEN).
Taguig City vs City of Makati Jurisdictional Ruling (G.R. No. 235316)
In 2021, the Supreme Court Special Third Division issued its final entry of judgment in G.R. No. 235316, affirming that Fort Bonifacio and the 10 Enlisted Men's Barrio (EMBO) barangays (Pembo, Comembo, Cembo, South Cembo, West Rembo, East Rembo, Pitogo, Post Proper Northside, Post Proper Southside, and Rizal) belong to the territorial jurisdiction of Taguig City. GIS datasets dated prior to 2023 list these under Makati City (PSGC 137602000). In current datasets, they resolve under Taguig City (PSGC 137607000).
Database Schema Design: Storing and Indexing PSGC in PostgreSQL
A frequent database anti-pattern is storing PSGC codes as numeric integers (INT or BIGINT). Because Northern Luzon regions use leading zeros (e.g., Ilocos Region is 01, Cagayan Valley is 02, Central Luzon is 03), integer types automatically strip the zero. This turns 037114000 into 37114000, breaking 9-character fixed-length string joins.
Always store PSGC codes as fixed-length or variable-length text fields with B-Tree indexes on administrative substring slices:
-- PostgreSQL / PostGIS Schema for PSGC Administrative Boundaries
CREATE TABLE ph_administrative_boundaries (
id SERIAL PRIMARY KEY,
psgc_code VARCHAR(10) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
admin_level VARCHAR(20) NOT NULL CHECK (admin_level IN ('region', 'province', 'city', 'municipality', 'barangay')),
region_code VARCHAR(2) GENERATED ALWAYS AS (SUBSTRING(psgc_code FROM 1 FOR 2)) STORED,
province_code VARCHAR(4) GENERATED ALWAYS AS (SUBSTRING(psgc_code FROM 1 FOR 4)) STORED,
geom GEOMETRY(MultiPolygon, 4326) NOT NULL
);
-- Fast B-Tree indexing on administrative slices
CREATE INDEX idx_admin_region ON ph_administrative_boundaries (region_code);
CREATE INDEX idx_admin_province ON ph_administrative_boundaries (province_code);
CREATE INDEX idx_admin_level ON ph_administrative_boundaries (admin_level);
-- Spatial index for point-in-polygon coordinates lookup
CREATE INDEX idx_admin_geom ON ph_administrative_boundaries USING GIST (geom);
-- Example: Find the exact LGU for a WGS84 GPS coordinate (e.g. Subic, Zambales)
SELECT psgc_code, name, admin_level
FROM ph_administrative_boundaries
WHERE ST_Contains(geom, ST_SetSRID(ST_Point(120.2315, 14.8803), 4326))
ORDER BY admin_level DESC;TypeScript Utility: Parsing 9-Digit and 10-Digit PSGC Codes
The utility below handles both legacy 9-digit and modern 10-digit formats, validates numeric format, and returns the structural hierarchy slices:
export interface PsgcEntity {
rawCode: string;
codeLength: 9 | 10;
regionPrefix: string;
provincePrefix: string;
cityMuniPrefix: string;
barangayPrefix: string;
isBarangay: boolean;
isValid: boolean;
}
/**
* Parses and validates a raw PSGC string into geographic hierarchy prefixes.
* Handles both 9-digit (legacy) and 10-digit (expanded) formats.
*/
export function parsePsgc(input: string | number): PsgcEntity {
const raw = String(input).trim();
const digitsOnly = raw.replace(/\D/g, '');
const isValidLength = digitsOnly.length === 9 || digitsOnly.length === 10;
if (!isValidLength) {
return {
rawCode: raw,
codeLength: 9,
regionPrefix: '',
provincePrefix: '',
cityMuniPrefix: '',
barangayPrefix: '',
isBarangay: false,
isValid: false
};
}
const length = digitsOnly.length as 9 | 10;
const regionPrefix = digitsOnly.slice(0, 2);
// In 9-digit codes: Province is 2 digits (pos 2-4), City is 2 digits (pos 4-6), Brgy is 3 digits
// In 10-digit codes: Province is 3 digits (pos 2-5), City is 2 digits (pos 5-7), Brgy is 3 digits
const provincePrefix = length === 9 ? digitsOnly.slice(0, 4) : digitsOnly.slice(0, 5);
const cityMuniPrefix = length === 9 ? digitsOnly.slice(0, 6) : digitsOnly.slice(0, 7);
const barangaySuffix = length === 9 ? digitsOnly.slice(6, 9) : digitsOnly.slice(7, 10);
const isBarangay = barangaySuffix !== '000';
return {
rawCode: digitsOnly,
codeLength: length,
regionPrefix,
provincePrefix,
cityMuniPrefix,
barangayPrefix: isBarangay ? digitsOnly : '',
isBarangay,
isValid: true
};
}
// Example usage:
const subic = parsePsgc('037114000');
console.log(subic.regionPrefix); // '03' (Central Luzon)
console.log(subic.provincePrefix); // '0371' (Zambales)
console.log(subic.isBarangay); // false (Municipal level)