The Shape of a Production Setup
When Sprout goes live at sprout.example.com, the pieces that shared your laptop spread across rented infrastructure. On AWS, a small app needs only a handful of services: one to answer DNS questions, one server, a private network, storage for files and a way to send email. What matters most is which pieces the internet can reach and which it cannot.
The rule
The name finds the server; the proxy faces the world; the database stays inside.
- Route 53 is AWS's DNS service. An
Arecord pointssprout.example.comat the server's public address, an Elastic IP that stays the same across restarts. - EC2 gives you a Linux virtual machine. Sprout's runs two programs: Nginx, the web server facing the internet, and the Node API.
- VPC is your private network inside AWS. PostgreSQL, for example on Amazon RDS, the managed database service, sits in a private subnet with no public address at all.
- S3 stores files. Plant photos go there, and PostgreSQL keeps just each photo's key.
- SES sends email: "Your fern is thirsty" reminders and password resets.
Nginx is the only program the internet talks to. It holds the HTTPS certificate, serves the built React files, and forwards API calls to Node:
server {
listen 443 ssl;
server_name sprout.example.com;
# ssl_certificate lines omitted
root /var/www/sprout; # the files from client/dist
location / {
try_files $uri /index.html; # let React handle paths like /plants/7
}
location /api/ {
proxy_pass http://127.0.0.1:3000; # the Node API, on this machine only
}
}A second small server block on port 80 redirects plain HTTP to HTTPS. Because pages and /api share one origin, CORS never comes up and the login cookie just works.
Who may connect to what is controlled by security groups, AWS's per-resource firewalls. The web server accepts ports 80 and 443 from anyone, and SSH on port 22 only from your own address. The database accepts port 5432 only from the web server's security group. Port 3000 is not opened at all; only Nginx on the same machine reaches it.
The shortcut
Trace a request from the outside in, and at each hop ask "Who can reach this?" DNS: everyone. Nginx on 443: everyone. Node on 3000: only Nginx. PostgreSQL: only the app server. If anything deeper than Nginx answers the open internet, close it.
The name
Her phone asks DNS for
sprout.example.com. Route 53 answers with the server's Elastic IP.
Drills
Answer fast — trust the rule.
Which AWS service answers "which address is sprout.example.com?"
Where should Sprout's PostgreSQL live?
What does Nginx do with a request for /api/plants?
Users upload plant photos. Where do the image files go?
Remember
- The name finds the server; the proxy faces the world; the database stays inside.
- Shortcut: trace outside-in and ask "who can reach this?" at every hop.
- Trap: opening the API port or the database to the internet "just to test". Only Nginx faces the world.
