27017
Where mongod and mongos listen by default — and the port a driver spends thirty silent seconds failing to select a server on.
Run the line for your platform. Each one names the process holding the port and the address it bound to, which is usually the whole answer.
sudo lsof -nP -iTCP:27017 -sTCP:LISTEN`-n` skips reverse DNS, `-P` skips port-name lookup, `-iTCP:27017` selects the port and `-sTCP:LISTEN` the listening state — the combination lsof's manual gives as an example. Take the PID from the second column and the bind address from the last, printed as `127.0.0.1:27017 (LISTEN)` or `*:27017 (LISTEN)`. A loopback bind is the default and is the answer to most 'the app cannot see the database' questions. A COMMAND of `com.docker.backend` means a published container port, so stop the container rather than that process. Run it under `sudo`, or a `mongod` owned by another user is invisible; with nothing listening, lsof prints nothing and exits 1.
sudo ss -tlnp 'sport = :27017'The ss(8) manual defines the flags used here: `-t` displays TCP sockets, `-l` displays only listening sockets, `-n` does not resolve service names, and `-p` shows the process using the socket; `sport = :27017` is its documented port filter. The Local Address:Port column is the whole diagnosis — `127.0.0.1:27017` is the localhost default and cannot be reached from another host, `0.0.0.0:27017` is every IPv4 address, `[::]:27017` is the IPv6 wildcard. The owner reads `users:(("mongod",pid=980,fd=12))`. Older hosts without `ss` can use `netstat -tlnp`; both need superuser privileges before they will name a process you do not own.
netstat -ano | findstr :27017From Microsoft's reference: `-a` displays all active TCP connections and the ports the computer is listening on, `-n` expresses addresses and ports numerically, `-o` includes the process ID for each connection. Columns run Proto, Local Address, Foreign Address, State, PID. Turn the PID into a name with `tasklist /fi "PID eq 980"` — `PID` is a documented filter and `eq` a documented operator. Because `findstr` matches a substring anywhere in the line, driver connections from this machine out to some other database on 27017 appear here too; the State column tells you which row is the listener.
Get-NetTCPConnection -LocalPort 27017 | Select-Object LocalAddress,LocalPort,State,OwningProcessThe PowerShell version matches the port as a number, so it never picks up a coincidental substring, and `-LocalPort` excludes connections where 27017 is the far end. `Get-Process -Id` on `OwningProcess` names the executable, which on Windows is usually the MongoDB service rather than a shell you started. An empty result while a bind keeps failing points at a reservation instead of an occupant: `netsh interface ipv4 show excludedportrange protocol=tcp` lists the blocks Hyper-V, WSL2 and Docker Desktop claim at boot.
mongosh --host 127.0.0.1 --port 27017 --eval 'db.runCommand({ ping: 1 })'The application-level check, and the one that separates a listening socket from a database that will actually serve you. `{ ok: 1 }` means healthy. An authentication error means healthy as well — the port, the bind address and the network are all fine and only credentials are missing. A thirty-second pause before any error means server selection timed out, which is a dropped packet rather than a refusal. Give the address explicitly rather than relying on a default so the answer is about the host you meant.
`nmap -Pn -p 27017 db.example.com` reports what the port looks like from off the machine. `-Pn` treats the host as online and skips discovery, which matters because database hosts often drop pings; `-p` limits the scan to the one port. `open` means the TCP handshake completed and something is listening. `closed` means the host answered with a reset, so it is up and routable but nothing holds the port — the usual signature of a stopped `mongod`. `filtered` means no answer came back at all, which is a firewall or a security group dropping the packet; that is also what your driver was waiting on for thirty seconds. `--reason` prints which of the three actually happened, `syn-ack` against an open port and `conn-refused` against a closed one, and `-sV` probes the port to determine the service and version — the same reading an internet-wide scanner takes when it is looking for unauthenticated databases. Scan only hosts you are responsible for.
| What you see | What it means |
|---|---|
MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017 | The socket layer refusing outright: the host answered with a reset because nothing holds the port. Either `mongod` is not running, or you are inside a container where `127.0.0.1` means that container and not the database. Address the database by its service name or the host's real address, and confirm with the probe for your platform on the machine that runs it. |
MongoServerSelectionError: Server selection timed out after 30000 ms | The driver's own wording once `serverSelectionTimeoutMS` expires, and its default is exactly 30000 milliseconds, so a hang of about thirty seconds is the tell. It is a wrapper, not a cause: the real socket error sits in the `reason` or in the topology description printed with it. Read that, and treat a timeout as a dropped packet and a refusal as a stopped server. |
MongoServerError: Authentication failed. | Error code 18, `AuthenticationFailed`. The network, the port and the bind address are all correct — the connection got as far as the handshake and the credentials were rejected. Check the user, the password and, most often, the `authSource`: a user created in `admin` does not authenticate against the application database unless you say so. |
MongoServerError: not authorized on appdb to execute command | Error code 13, `Unauthorized`, and again nothing to do with 27017. You authenticated successfully and the role attached to that user does not carry the privilege for the command you ran. Grant the role on the right database rather than reaching for a root user. |
listen EADDRINUSE: address already in use 0.0.0.0:27017 | Something already holds the port — usually an installed MongoDB service starting at boot beside the container you just brought up, or an earlier `mongod` that never exited. Find the owner first; publishing the container on another port is often the faster fix than stopping the service. |
mongod logs 'Waiting for connections' with a port you did not expect | That startup line carries the port it actually took, and it is the fastest way to catch a config file overriding you. A `mongod` given `--shardsvr` defaults to 27018 and one given `--configsvr` to 27019, so a member of a sharded cluster is frequently not on 27017 at all, however the connection string reads. |
IANA registers 27017 to `mongodb`, 'Mongo database system', on TCP; the UDP row is Reserved and carries no service name. MongoDB's own reference lists the sibling numbers, and knowing them saves a lot of guessing: 27017 is the default for both `mongod` and `mongos`, 27018 is the default for a `mongod` started with `--shardsvr` or with `clusterRole: shardsvr`, 27019 is the default for `--configsvr`, and 27020 is where `mongocryptd` listens. None of those siblings appear in the IANA registry — only 27017 does. Current MongoDB binaries bind to localhost by default; the manual says so directly, and it names the ways to widen that: `0.0.0.0` for every IPv4 address, `::,0.0.0.0` for both families, or the `net.bindIpAll` setting. That default is the single most common reason a database that answers perfectly over a shell on the server is unreachable from an application host. The other thing worth knowing is that failures here are usually reported through server selection rather than through the socket: a driver keeps retrying every node in its topology until `serverSelectionTimeoutMS` runs out, and that defaults to 30000 milliseconds, so a wrong port or a blocked one presents as a thirty-second hang rather than an immediate error.
27017 must not be reachable from the internet. Authorization is something you switch on, and a database started without it accepts every command from anyone who can open the socket — which is exactly how large numbers of exposed deployments were emptied and held for ransom once scanners started sweeping the port. The localhost default is a genuine improvement, but it protects only a server nobody has reconfigured; the moment `bindIp` is widened so an application host can connect, the database is as reachable as the network allows. MongoDB's guidance is to keep instances 'only accessible on trusted networks', and, on a machine with more than one network interface, to bind to the private or internal one rather than to everything. Do that first. Then create an administrative user and enable authorization, and give each application its own role-scoped user instead of a root one, so a leaked credential is a bounded loss. Reach a database from outside its network over a VPN, a peered private subnet or an SSH tunnel rather than by opening the port at the firewall; where it genuinely must be routable, restrict it by source address and require TLS, because without it credentials, queries and returned documents all cross the network readable.
All of these run in your browser — nothing is uploaded.
Ports people usually end up checking in the same session as 27017.
Almost always permissions. lsof and ss list the socket but hide the owning process when it belongs to another user, so a server started by a system account, by a container runtime or by launchd shows up as an anonymous listener until you re-run the command with sudo. On Windows the opposite happens: netstat shows nothing at all, yet a bind still fails, which means the port sits inside a range that Hyper-V, WSL2 or Docker Desktop reserved at boot.
Look at what it is first. An orphaned dev server is safe to kill; a database with a write in flight is not, and neither is a system service that something else depends on. If the owner is a container, stop the container instead — killing the process the host sees only makes the runtime restart it. When the process is something you need, moving your own service to another port is the faster fix.
The listener bound to 127.0.0.1 rather than 0.0.0.0. The probes on every page print the bound address next to the process for exactly this reason: a loopback bind is reachable from the machine itself and from nowhere else, no matter how the firewall is configured. Many frameworks made that the default deliberately, so it is usually a flag rather than a bug. If the address is already 0.0.0.0 and it still fails, the next suspect is a host firewall or a cloud security group.
Barely. Internet-wide scanners sweep the whole port range continuously, so an unusual number buys hours, not safety, and it costs you every colleague who now has to remember it. It does cut the noise in your logs from opportunistic scans of the default port, which is a real if modest benefit. Authentication, a firewall that restricts source addresses, and not exposing the service at all are the measures that actually change the outcome.
Still stuck on port 27017? browse every port in the reference — or go back to the failure message you actually got, above.