I’m building a simple TCP server in Node.js to retrieve large PDF files from clients. Everything works fine when I send data from the same machine (localhost) — I get large chunks of 65536 bytes and the file is saved almost instantly.
However, when I send the same file (around 20 MB) from a remote machine over the local network, the data.length drops to around 1436 bytes per chunk, and the server receives the relevant file very slowly (about 30 seconds, which is very slow), even though my internet connection is good (around 64 Mbps).
To be specific:
Local connection: Chunks are ~65536 bytes, total transfer time ≈ 1 second
Remote connection: Chunks are ~1436 bytes, total transfer time ≈ 20 seconds
Here’s a simplified version of my TCP server code:
const net = require("net");
const crypto = require("crypto");
const fs = require("fs");
require("dotenv").config();
const server = net.createServer((socket) => {
socket.setNoDelay(true);
const chunks = [];
socket.on("data", (data) => {
chunks.push(data);
console.log(data.length); // 65536 for localhost, 1436 for remote clients.
if (data.toString("utf8").endsWith("DONE")) {
const bytes = Buffer.concat(chunks).slice(0, -(Buffer.from("DONE", "utf8").length));
console.log(bytes.length); // 20 MB
fs.writeFile(crypto.randomUUID() + ".bin", bytes, (err) => socket.write(JSON.stringify({ success: !err })));
}
});
});
server.listen(process.env.PORT, process.env.DEDICATED_SERVER_IPV4, () => console.log("Running..."));
Here’s a simpler version of my TCP client code:
const net = require("net");
const fs = require("fs");
require("dotenv").config();
fs.readFile("file.bin", (err, bytes) => {
if (!err) {
console.log(bytes.length); // 20 MB
const client = net.createConnection({ port: process.env.PORT, host: process.env.DEDICATED_SERVER_IPV4 }, () => {
client.write(bytes);
client.write("DONE");
});
client.on("data", (data) => console.log(data.toString()));
} else console.error(err.stack);
});
What I’ve tried:
Increased highWaterMark to 1 MB.
Called socket.setNoDelay(true) to disable Nagle’s algorithm.
Verified that the issue only occurs when the sender is on a different machine.
Same file, same code — only difference is local vs remote client.
My questions:
Why does data.length drop to ~1436 bytes and is the file transfer very slow when the client is remote?
Is this caused by TCP MSS, MTU, or buffering behavior in Node.js or the OS?
And the most important one: How can I optimize my TCP server for faster large file uploads over remote connections?
Any help or insights would be greatly appreciated!
Thanks in advance.