Why are Foreign Data Wrappers (FDW) a Lifesaver?
Fragmented data is a constant nightmare for every developer. Imagine this: user information is in MySQL, activity logs are stuck in MongoDB, and the promotion list is in a 500MB CSV file sent by the Marketing team over Slack. The old way was to write Python scripts or build bulky ETL pipelines to consolidate everything. However, maintaining those pipelines is exhausting.
I once had a task to migrate a reporting system from MySQL to PostgreSQL. Instead of spending 3 days writing a synchronization tool, it took me exactly 45 minutes to configure Foreign Data Wrappers (FDW). FDW turns PostgreSQL into a true “Data Hub.” You can directly JOIN local Postgres tables with remote MySQL tables as if they were in the same database. Data is queried using standard SQL syntax without having to copy a single byte to the local machine.
The biggest advantage here is immediacy. As soon as MySQL gets a new order, it’s visible in Postgres—no need to wait for periodic ETL jobs. FDW isn’t a silver bullet for every performance problem, but for quick reporting, migrations, or data reconciliation, it is truly a powerful weapon.
Installing the Necessary Extensions
By default, PostgreSQL only comes with postgres_fdw to connect between Postgres servers. To extend its reach to MySQL or MongoDB, you need to install the corresponding drivers from your operating system’s repository. On Ubuntu, run the following command:
# Install support libraries for MySQL and CSV
sudo apt-get install postgresql-15-mysql-fdw
sudo apt-get install postgresql-15-mongo-fdw
After installing at the OS level, log into Postgres as a superuser to enable the extensions. This is a mandatory step for the database to recognize the new wrappers.
-- Enable extensions
CREATE EXTENSION mysql_fdw;
CREATE EXTENSION file_fdw;
CREATE EXTENSION mongo_fdw;
Detailed Configuration for Each Data Source
1. Connecting to MySQL
This is the most common real-world scenario. The setup process consists of 4 clear steps: declaring the server, mapping the user, and importing the tables.
-- Step 1: Declare the remote MySQL server
CREATE SERVER mysql_server
FOREIGN DATA WRAPPER mysql_fdw
OPTIONS (host '192.168.1.50', port '3306');
-- Step 2: Map the current Postgres user to the MySQL user
CREATE USER MAPPING FOR current_user
SERVER mysql_server
OPTIONS (username 'db_user', password 'secure_password');
-- Step 3: Import the entire schema to save time
IMPORT FOREIGN SCHEMA production_db
FROM SERVER mysql_server
INTO local_mysql_schema;
2. Reading Large CSV Files
Did your boss just drop a 5GB CSV file on you and demand an immediate data audit? Instead of using the COPY command which consumes disk space, use file_fdw to read directly from the file.
-- Initialize the server for files
CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
-- Create a foreign table linked to the CSV file
CREATE FOREIGN TABLE csv_logs (
log_date date,
log_level text,
message text
) SERVER file_server
OPTIONS (filename '/var/lib/postgresql/data/logs.csv', format 'csv', header 'true');
-- Query directly like a normal table
SELECT log_level, count(*) FROM csv_logs GROUP BY 1;
3. Connecting to MongoDB (NoSQL)
Casting from Document to Relational can sometimes be a bit tedious. mongo_fdw handles this by mapping BSON fields into fixed columns in Postgres.
-- Configure the MongoDB server
CREATE SERVER mongo_server
FOREIGN DATA WRAPPER mongo_fdw
OPTIONS (address '127.0.0.1', port '27017');
-- Map the collection to a foreign table
CREATE FOREIGN TABLE mongo_logs (
_id text,
user_id int,
action text
) SERVER mongo_server
OPTIONS (db 'app_logs', collection 'activity_logs');
Performance and Security Optimization Strategies
The most common mistake is treating a Foreign Table like a local table. Remember that the network is always the biggest bottleneck. If you JOIN two MySQL and Postgres tables with millions of records, the server bandwidth will quickly become congested.
Leverage Predicate Pushdown
Pushdown is a vital feature of FDW. When you write WHERE id = 10, Postgres pushes this condition to the MySQL side to filter first. This reduces the amount of data transmitted over the network. Always use EXPLAIN ANALYZE to check your queries.
EXPLAIN ANALYZE
SELECT p.name, m.email
FROM local_products p
JOIN remote_users m ON p.user_id = m.id
WHERE m.status = 'active';
If you see a Remote SQL line in the output, it means Pushdown is working. Conversely, if Postgres pulls the entire table and then filters it, your server will soon be struggling.
Notes on Data Security
Password information in USER MAPPING is stored in metadata. You should only grant USAGE permissions to users who actually need them. A small tip is to always use a Read-Only account on the source side (MySQL/Mongo). This helps avoid the risk of accidentally running a DELETE command and wiping out the original data.
In summary, FDW makes data architecture much cleaner and more flexible. It solves the problem of distributed data without the need to maintain complex ETL pipelines. If you are dealing with a multi-source system, try setting up FDW today.

