Private networking: services talk to each other without ever touching the public internet
Cloud Computing's own VPC lesson (via AWS) covered building a private network by hand — subnets, route tables, security groups. Railway gives every project a private network automatically, with zero networking configuration, and that default is one of the platform's single most distinctive, genuinely useful features.
Intermediate
2 min read
Every service gets a private, internal hostname automatically
Service "api" can reach the database at:
postgres.railway.internal:5432
Service "web" can reach the API at:
api.railway.internal:3000
Every service within a Railway project automatically gets a private DNS hostname reachable only from other services in the same project — no public internet routing involved at all, and no manual VPC, subnet, or security-group configuration the way AWS's own VPC lesson walks through building by hand. This is the exact same underlying goal (services communicating without exposing themselves publicly) that a hand-built private network achieves, just provided as a zero-configuration default instead of something a team assembles themselves.
Why this matters for real security, not just convenience
A database with no public endpoint at all is immune to an entire class of attack that Web Security's own domain covers extensively (SQL injection still matters, but a database that's simply unreachable from outside the private network can't be directly probed, brute-forced, or scanned by an internet-wide attacker at all) — this is Application Security's own defense-in-depth principle, applied structurally by the platform's default networking behavior rather than something a team has to remember to configure correctly on their own.
Reference variables: connecting services without hardcoding anything
In the "api" service's environment variables:
DATABASE_URL = ${{Postgres.DATABASE_URL}}
Rather than manually copying a database's connection string into every service that needs it (and needing to update every copy whenever it changes), Railway's reference variables let one service's configuration directly reference another service's own variable — ${{Postgres.DATABASE_URL}} always resolves to whatever the actual Postgres service's connection string currently is, automatically staying correct even if that value ever changes (a credential rotation, a host migration) without anyone needing to hunt down and update every service that depends on it.
Public networking: explicitly opting a service INTO internet exposure
By default, a service is reachable only privately — making it publicly reachable (the web frontend, an API meant for external clients) requires explicitly generating a public domain for it. This default-private, opt-in-public posture is itself a real security property: a service that was never meant to be public-facing (a worker, an internal admin tool, the database itself) simply has no public attack surface to begin with, because nobody had to remember to not expose it — the default already didn't.