Sent when the server has received the request headers and the client should proceed to send the request body. Used when sending large files — the client checks if the server is ready before uploading.
Expect: 100-continue
→ Server responds: 100 Continue
→ Client now sends the file body
The server agrees to upgrade the protocol. Most commonly seen when upgrading from HTTP to WebSockets — the connection becomes a persistent, two-way channel.
Upgrade: websocket
Connection: Upgrade
→ HTTP/1.1 101 Switching Protocols
→ Upgrade: websocket
A WebDAV extension code indicating the server has received the request but hasn't finished processing. Prevents the client from timing out on long operations.
The standard success response. The meaning depends on the HTTP method: GET returns the resource, POST returns the result, PUT returns the updated resource. Your ALB health checks should always aim to see 200 from your EC2 targets.
EC2 instance is HEALTHY ✓
GET /api/users → 200 OK
{"users": [...], "count": 42}
Returned after a POST request successfully creates a resource. The response typically includes a Location header pointing to the new resource's URL.
{"name": "Anji", "role": "cloud-engineer"}
→ 201 Created
Location: /api/users/123
The request has been accepted for processing, but processing hasn't completed. Common with async jobs — like triggering an AWS Lambda or SQS message and returning immediately while processing happens in background.
The server successfully processed the request but is not returning any content. Used for DELETE operations, or PUT updates where you don't need to return the full resource back to the client.
→ 204 No Content
(no response body)
Used when the client sends a Range header to request only part of a resource. Common in video streaming, S3 byte-range reads, and download resumption.
Range: bytes=0-1023
→ 206 Partial Content
Content-Range: bytes 0-1023/5242880
The resource has permanently moved to a new URL. Browsers cache this. Search engines transfer SEO juice. In AWS, you'll configure 301 redirects on ALB listener rules — for example, forcing HTTP → HTTPS.
Action: Redirect to HTTPS
Status Code: 301
GET http://anjidevops.online
→ 301 → https://anjidevops.online
Temporary redirect — the original URL is still valid. Browsers don't cache this. Use 301 for permanent changes, 302 for temporary ones (maintenance pages, A/B testing).
The server tells the client "your cached copy is still fresh, use it." No body is sent, saving bandwidth. CloudFront uses this extensively for cache validation. Triggered by If-Modified-Since or ETag headers.
If-None-Match: "abc123"
→ 304 Not Modified
(no body — use cached copy)
Temporary redirect that guarantees the HTTP method won't change. If a POST is redirected with 302, some browsers change to GET. 307 prevents this — POST stays POST.
Permanent redirect that preserves the HTTP method. The modern, stricter version of 301. If you POST to a URL and it's permanently moved, 308 ensures the client POSTs to the new URL too.
The server cannot process the request due to invalid syntax. Often caused by malformed JSON, missing required fields, or invalid query parameters. The client must fix the request before retrying.
{"region": "ap-south-1", "count": } ← broken JSON
→ 400 Bad Request
{"error": "Invalid JSON syntax at line 1"}
Despite the name, this is about authentication, not authorization. The client must authenticate to get the requested response. Common with expired JWT tokens, missing API keys, or invalid AWS credentials.
Authorization: Bearer eyJ... (expired)
→ 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
The client is authenticated but lacks permission. In AWS, this is extremely common — IAM policy denies, S3 bucket policies, Security Group blocks. The key difference from 401: re-authenticating won't help.
IAM user: dev-user
→ 403 AccessDenied
Bucket policy blocks this IAM principal
The server can't find the requested resource. The URL is valid, but there's nothing there. Also used to hide existence of resources for security. If your ALB target returns 404, check your Nginx config and file paths.
Nginx root: /var/www/html/
File: /usr/share/nginx/html/index.html
→ 404 Not Found (wrong root path)
The endpoint exists, but doesn't support the HTTP method used. E.g. sending a DELETE to a read-only endpoint, or POST to a GET-only route. The response includes an Allow header listing valid methods.
→ 405 Method Not Allowed
Allow: GET, POST
The client took too long to send the request. ALB has an idle timeout (default 60s). If a client opens a connection but doesn't send a request within that window, the connection is closed.
The request conflicts with the current state. Classic examples: trying to create a user that already exists, editing a resource that was modified by someone else (version mismatch), or duplicate record violations.
{"email": "anji@example.com"}
→ 409 Conflict
{"error": "User with this email already exists"}
The resource existed but has been permanently removed. Unlike 404, 410 tells clients and search engines definitively: this is gone forever, stop requesting it and remove it from your index.
The request was well-formed but failed semantic validation. JSON is valid, but the data doesn't make sense. Common in REST APIs and form submissions — age: -5, or an email field with "notanemail".
{"instance_type": "invalid_type", "count": -1}
→ 422 Unprocessable Entity
{"errors": ["Invalid instance_type", "count must be > 0"]}
The client has sent too many requests in a given time. Critical for API rate limiting and DDoS mitigation. AWS API Gateway returns 429 when throttling. Response includes Retry-After header with seconds to wait.
Limit: 100 req/sec
→ 429 Too Many Requests
Retry-After: 10
X-RateLimit-Remaining: 0
The server encountered an unexpected condition. The generic server-side error. Could be: unhandled exception in your app code, database query failure, memory overflow, or misconfigured application. Check your CloudWatch logs immediately.
→ CloudWatch Alarm: ALARM state
→ Check Nginx error.log on EC2:
[ERROR] Unhandled exception: DB connection refused
The server doesn't know how to handle the request method. Unlike 405 (method not allowed for this route), 501 means the server doesn't implement this HTTP method at all. Rare in practice.
The gateway (e.g. Nginx, ALB) received an invalid response from the upstream backend. In AWS: ALB forwards request to EC2 → EC2 returns garbage or crashes mid-response → ALB shows 502 to client. Also seen when EC2 is misconfigured or Nginx upstream is wrong.
EC2 Nginx crash or wrong upstream port
→ ALB returns 502 Bad Gateway
Fix: Check target group health in ALB console
Check: sudo journalctl -u nginx -n 50
The server is temporarily unable to handle the request. In AWS: all ALB targets fail health checks → ALB returns 503 to all incoming requests. This is your biggest production alert. Add a Retry-After header during planned maintenance.
Target 10.0.1.5:80 → UNHEALTHY
Target 10.0.2.5:80 → UNHEALTHY
→ All requests return 503
→ CloudWatch: HealthyHostCount = 0 → ALARM
The gateway didn't receive a timely response from the upstream server. In AWS: ALB idle timeout is 60s by default. If EC2 takes longer than 60s to respond, ALB returns 504. Fix: increase ALB idle timeout, or optimize slow queries.
ALB idle timeout: 60s (default)
→ 504 Gateway Timeout
Fix Option 1: ALB console → Attributes
→ Idle timeout: 120 seconds
Fix Option 2: Optimize the slow query
The server doesn't support the HTTP protocol version used. Rare in modern infrastructure. Can appear when a client tries HTTP/3 against a server only supporting HTTP/1.1.