Use case

Hand a teammate a connection string to your local database.

A database is running on your machine and someone who is not on your network needs to query it. A raw TCP tunnel gives that port a public address, so their client connects with an ordinary connection string. TCP tunnels start on Professional at $4 a month.

One command, one connection string

tunnels tcp 5432 opens a raw TCP tunnel to the port your database listens on. The client prints a public host and a port, and that pair is the whole handover.

$ tunnels tcp 5432
Active Tunnels:
  ▸ tcp://tunnels.host:41287 → 127.0.0.1:5432  [tcp]

The port is assigned when the tunnel opens, so read it off the client rather than hard-coding it. The connecting side pastes the ordinary URL for that database with our host and port in place of the local one.

postgresql://appuser:PASSWORD@tunnels.host:41287/appdb?sslmode=require
mysql://appuser:PASSWORD@tunnels.host:41287/appdb
redis://:PASSWORD@tunnels.host:41287/0
mongodb://appuser:PASSWORD@tunnels.host:41287/appdb?directConnection=true
amqp://appuser:PASSWORD@tunnels.host:41287/

psql, a GUI browser, an ORM datasource and redis-cli all take a host and a port, and none of them care that this one is ours.

Why does the connection time out when the tunnel is up?

This is the failure that eats the first hour. Two things must be true: the tunnel client has to open a TCP connection to the database, and the database has to authenticate that account over the connection it receives.

If client and database share a machine, a loopback-only bind is fine, because the client dials 127.0.0.1 as any local tool would. The moment they do not, and that includes a database in a container with the client on the host, the loopback bind is the wall. listen_addresses, bind-address, bind and net.bindIp, in postgresql.conf, my.cnf, redis.conf and mongod.conf, all ship pointed at loopback.

Host-based rules catch the rest. Postgres consults pg_hba.conf, and MySQL stores the allowed host inside the account, so 'appuser'@'localhost' is a different account from 'appuser'@'%'. The symptom misleads because the tunnel client looks healthy either way: it has a live public port and nothing to hand traffic to.

What does each database need?

All five are plain TCP, so the tunnel treats them identically. What differs is whether the client speaks TLS of its own, and the thing that catches people out.

Service Default port Speaks its own TLS What usually goes wrong
PostgreSQL 5432 Yes, requested with sslmode No pg_hba.conf rule matches the new source address.
MySQL 3306 Yes, preferred when a certificate exists The account is user@localhost, so it does not exist remotely.
Redis 6379 Optional, off by default No password is set, and protected mode refuses non-loopback clients.
MongoDB 27017 Yes, off in most local installs The driver finds a replica set and chases a hostname the caller cannot resolve. Add directConnection.
RabbitMQ 5672 Yes, on a listener you enable The guest user is loopback-only, so local credentials fail remotely.

Anything else speaking TCP behaves the same way. Anything needing UDP does not work at all.

What are you putting on the internet?

A database port, with whatever authentication it was given locally. Local databases are configured for convenience: trust authentication, a reused password, a superuser doing ordinary work. None of that matters on loopback. All of it matters on a public port, which gets scanned within minutes.

Do not do this with production data.

A tunnel to a production database is a production database on the public internet, and no care taken over the tunnel changes that. Use a development copy, or a restored dump with the personal data stripped. If the only copy of what you are exposing is the one your customers depend on, stop and make one.

Four habits make the rest survivable: a dedicated account with the narrowest grants that do the job, a long random password from a tool, a tunnel that lives no longer than the conversation, and a copy of the data rather than the real thing. Only the last one fails safe on its own.

Does the tunnel encrypt the database protocol?

No, and this is the part people get wrong. There are two legs. The leg from the tunnel client up to our edge runs over TLS, negotiated per connection, TLS 1.3 where both ends support it and TLS 1.2 as the floor. The leg from whoever is connecting down to the public port is raw TCP, because that is what a raw TCP tunnel is. Whatever the protocol puts on that wire is what travels.

So turn the database's own TLS on and require it from the client. Postgres uses sslmode=require, MySQL and MongoDB have equivalents, Redis and RabbitMQ want a second listener enabled first. Then the payload is encrypted between the two things that actually speak the protocol. Treat the tunnel as transport, not as confidentiality. The mechanics are in how an outbound connection carries inbound traffic.

Which plan you need

Professional, at $4 a month or $40 a year. Raw TCP starts there and is not available below it: the free Basic plan and the Student plan carry HTTPS only, so neither can open a TCP tunnel. There is no version of this use case that runs on the free plan, and we would rather you read that here than discover it after signing up.

Professional gives you five concurrent tunnels, but they are split by protocol: at most one raw TCP tunnel and up to four HTTPS ones. One database at a time, in other words. Gold at $10 a month drops the split and gives ten tunnels of any kind. Professional also carries 128 GB of transfer a month. The number to watch on a database tunnel is a different one: concurrent TCP connections, capped at ten on Professional and fifty on Gold, uncapped on Premium. A connection pool sized at twenty will exhaust the Professional cap on its own, so size the pool deliberately or take Gold. Gold at $10 a month also raises the tunnel count to ten and transfer to 256 GB; Premium at $20 a month is unlimited tunnels and 512 GB. Pricing is the authoritative copy.

What this does not do

No UDP, no SMTP

The engine carries HTTPS and raw TCP and rejects everything else by name, on every plan.

No access control at our edge

No IP allowlist, no OAuth, no SSO. The --httpauth flag is an HTTP mechanism and does nothing for a TCP port. Your database's authentication is the gate.

It is not hosting

The database stays on your machine. Auto-reconnect covers a network blip, not a laptop that went to sleep.

There is also no query logging and no request replay. The inspector on 127.0.0.1:4040 shows HTTP requests, not a raw TCP stream.

How do you close the tunnel when you are done?

Stop the client. Interrupt it in its terminal and the public listener goes with it: the port is released, open connections drop, and there is nothing left to revoke.

Do it deliberately rather than eventually. The client reconnects on its own after an interruption, with exponential backoff and jitter. That is what you want during an afternoon of work and what you do not want overnight, because a tunnel you forgot about is a database port on the internet behind a password you chose in a hurry. Then drop the account you created and put the bind address back.

Questions

Can I connect to a local PostgreSQL database from another machine?

Yes, over a raw TCP tunnel. Run the client against port 5432 and it prints a public host and port on tunnels.host. The other side puts that pair into an ordinary connection string in place of localhost. Postgres still has to accept it, so listen_addresses and pg_hba.conf both have to allow it.

Does a database tunnel work on the free plan?

No. The free Basic plan and the Student plan carry HTTPS only. Raw TCP starts on Professional at $4 a month, or $40 a year. Gold and Premium include TCP too.

Why does my client time out when the tunnel says it is connected?

Almost always because the database is not reachable from where the tunnel client runs, or because a host-based rule rejects the new source address. Check the bind setting first, then the authentication rules: pg_hba.conf, the host part of a MySQL account, protected mode for Redis.

Is the traffic encrypted?

The leg from the tunnel client to our edge runs over TLS, TLS 1.3 where both ends support it and TLS 1.2 as the floor. The public leg is raw TCP, so it carries whatever the database protocol puts on the wire. Enable the database's own TLS and require it from the client if the queries or results matter.

Can I restrict who is allowed to connect to the port?

Not at our edge. There is no IP allowlisting and no OAuth in front of a tunnel, and the basic auth flag applies to HTTP tunnels rather than TCP ones. Anyone holding the host and port can open a connection, so the controls that matter are the database's: a dedicated account, a strong password and minimal grants.

Open the port, share the string, close it again.

TCP tunnels start on Professional at $4 a month. Run one command against the port your database is on, then hand over a connection string that works from anywhere.