Skip to content

Engineering

We Changed Ankik's Infrastructure Three Times. Here's Why.

From AWS EC2 + RDS to a ₹520 private VM and finally AWS Lightsail — what Ankik learned about cost, latency, reliability, and operational uncertainty.

Dhanji Bhagat

Dhanji Bhagat

Founder & Principal Engineer

8 min readUpdated
hostingAWSLightsailEC2RDSPostgreSQLinfrastructureAnkik

We didn’t keep changing Ankik’s infrastructure because we couldn’t decide. We changed it because the constraints changed — and each move taught us what mattered next.

Ankik’s journey has had three stages: managed AWS, a private VM that looked best on price, and now AWS Lightsail. Each stage was correct for the problem we were solving at that time.

VM vs RDS — COST IS NOT THE ONLY BILL

AWS (snapshot July 2026)

EC2 t3.small $18 + RDS db.t3.micro $16 + ~$5 = $39/mo

  • Managed · auto backup & patch · ~180ms Gujarat
  • ✓ Zero ops burden

USD card + forex. Recommended when no one owns ops.

Private VM (Mumbai)

2 vCPU · 4 GB · Postgres on same VM + ~Rs 40 S3 · Rs 520/mo

  • You run backups · patches · restarts · ~28ms Vadodara
  • ⚠ You own the checklist

INR/UPI. ~84% lower infra bill in snapshot — ops time excluded.

When each fits — 5 checks before you migrate

  • Business fit

    job coverage?

  • Team

    who patches?

  • Cost

    VM + S3 + hours

  • Security

    backups encrypted?

  • Migration

    rollback?

We chose the VM for Ankik beta (~50 users, <20 GB) because someone owns backups & 15-day restore test.
If no one owns ops or you need PITR, keep RDS. Full note: /reframehub/self-hosted-postgres/

The bill you see vs the bill you operate — why the cheapest VM per rupee was not the cheapest to run.

TL;DR: EC2 + RDS (~$39/mo for ~50 beta users) → ₹520 VM (84% cheaper infra bill, more uncertainty to own) → Lightsail 2 GB (predictability over raw RAM). We resize when we observe sustained pressure, not the plan page.

We changed Ankik’s infrastructure three times

Ankik runs on PostgreSQL. For a long time the data lived across notebooks, Excel, and WhatsApp — but the infrastructure story is more recent.

This is a founder-written field note. It documents three real moves, what we actually paid, what we learned, and why we now run on Lightsail. It is not a generic hosting comparison and not an AWS promotion.

The progression is:

AWS EC2 + RDS → ₹520 Private VM + self-hosted PostgreSQL → AWS Lightsail + self-hosted PostgreSQL

Stages 1 and 2 are historical snapshots. Stage 3 is current. We do not mix the old $39 figure with Lightsail pricing, and we do not present Lightsail as immune to downtime.

Stage 1 — EC2 + RDS

Ankik initially ran with:

  • EC2 for the application
  • RDS for PostgreSQL
  • AWS-managed database infrastructure
  • Higher operational convenience — daily backups, auto patches, auto restart
  • Higher monthly infrastructure cost

At that point this was not a mistake. It was the reasonable default: managed infrastructure lets a small team focus on the product, and the application and database were cleanly separated.

We documented this starting point in our self-hosted Postgres field note. The snapshot below is from that note.

Why we left managed AWS

The workload was still small and beta-scale — roughly ~50 beta users — and the managed bill felt disproportionate.

Historical July 2026 deployment snapshot (not a current AWS price quote):

  • EC2 t3.small — $18/mo
  • RDS db.t3.micro — $16/mo plus storage
  • EBS and transfer — ~$5/mo
  • Total: ~$39/mo (~₹3,300, USD billing, ~180 ms from Gujarat in that placement)

That total is a historical measurement excluded team operating time and is not a quote you should re-price from today. The reason we reconsidered was not that RDS failed — it worked well. It was that ~$39/mo for ~50 beta users was more than Ankik needed at that stage, and the separated architecture added cost and latency we could consolidate.

Stage 2 — the ₹520 private VM

We moved from EC2 + RDS → one private VM, moving PostgreSQL onto the same machine.

Historical characteristics from 10 July 2026:

  • 2 vCPU, 4 GB RAM
  • ~₹520/month (INR/UPI billing)
  • Self-hosted PostgreSQL (Rs 0 extra compute — it shares the VM’s RAM)
  • Backups to S3 — ~Rs 40/mo
  • Application and database colocated — ~28 ms from Vadodara when measured, no connection caps like some serverless Postgres
  • About 84% lower infra bill in that snapshot — excluding team time

The VM worked. For roughly a month we had zero data loss and one manual restart after an OOM on 2 GB — we then moved to 4 GB and added Uptime Kuma → Telegram. We enabled pg_stat_statements for slow-query visibility, a small win that was easier with full control.

The private VM was attractive because it dramatically reduced infrastructure cost and provided more raw resources per rupee. Raw resources and low price, however, are not the only variables that matter.

What the private VM taught us

The private VM was cheaper and more powerful on paper, but it required us to own more infrastructure-level uncertainty.

Not a dramatic outage — the note records only that single OOM — but the broader concern: how standardized the VPS management was, how networking behaved, how IP continuity was handled, and how much of the underlying environment we had to reason about ourselves.

The correct framing is:

The private VM was cheaper and more powerful on paper, but it required us to own more infrastructure-level uncertainty.

Operations still had a cost, even when the infra bill approached zero. That trade is visible in our own words from the field note: marginal infra cost can be near zero if a correctly sized 4 GB VM already exists; operations still cost time.

Why we moved again

We did not move because the VM couldn’t handle the load. We moved because the optimization target changed.

Previously:

Maximize resources while minimizing infrastructure cost.

Now:

Maximize predictability and operational confidence while keeping the architecture simple.

The decision was not primarily about getting more CPU or RAM — we actually accepted less RAM. It was about reducing uncertainty in the infrastructure layer so the team can reason about the system at 2 a.m.

Stage 3 — AWS Lightsail

Ankik now runs on AWS Lightsail.

Current setup:

  • AWS Lightsail
  • 2 vCPU, 2 GB RAM, 60 GB SSD
  • Self-hosted PostgreSQL
  • Docker
  • Caddy
  • MinIO
  • Dozzle
  • Static IPv4 attached to the Lightsail instance

Current stack on Lightsail:

AWS Lightsail
│
├── Caddy
├── Ankik Backend
├── PostgreSQL
├── MinIO
└── Dozzle

Lightsail provides a simpler VPS-style experience without immediately returning to the larger EC2 + RDS cost profile. It is backed by AWS infrastructure and the ecosystem we already use elsewhere, with a console and networking primitive we can reason about.

We do not claim a single Lightsail instance provides 99.99% uptime. That is too broad for a single VPS. If you need that level of SLA you need multiple instances across zones — a path we have not built. If discussing AWS’s SLA, verify the current AWS documentation and distinguish single-instance from multi-instance architectures.

Why 2 GB is enough for now

The previous VM had 4 GB RAM. Lightsail has 2 GB RAM. We deliberately accepted less RAM.

We did that because the 2 GB Lightsail instance is currently sufficient for the Ankik beta workload:

  • Ankik’s Docker stack is lightweight. App, Postgres, Caddy, and MinIO comfortably share 2 GB at current load.
  • We monitor actual consumption rather than sizing for a hypothetical peak.
  • We do not claim 2 GB is universally enough for all future Ankik workloads.
  • If memory pressure becomes a sustained production constraint, we can resize the Lightsail instance — a documented scale step, not a rebuild.

We stopped sizing for the biggest number on the plan page and started sizing for the steady-state we actually observe. That is the opposite of the early “model the whole business on day one” mistake described in Ankik’s ledger story.

Static IP and infrastructure predictability

On Lightsail we attached a Lightsail Static IPv4.

A normal public IPv4 can change after certain stop/start operations, while a Static IPv4 remains associated with the instance. You allocate it, attach it, and DNS can point to a stable address.

This reduces surprises involving DNS, allowlists, external integrations, and service configuration.

We do not imply Lightsail automatically provides a static IP unless one is explicitly attached, and we do not claim a Static IPv4 prevents every networking issue. A misconfigured Caddy, an expired DNS record, a security group change, or a bad deploy can still make the app unreachable. Static IP solves one specific class of surprise — the address itself changing.

Monitoring and failure detection

Ankik today runs fully containerized. Our current monitoring on Lightsail is:

  • Docker restart policies on every service
  • Persistent volumes for Postgres and MinIO data
  • PostgreSQL backups — regular dumps, with instance snapshots where appropriate
  • Dozzle for logs — we watch container lifecycle events in one place
  • Dozzle alerts for container restarts, OOM kills, health issues, and CPU/memory thresholds
  • Discord for infrastructure and container alerts (Dozzle → Discord)
  • Google Chat for CI/CD notifications (deploy pipeline → Chat)
  • Application health endpoints that verify the app can reach Postgres
  • External uptime monitoring that probes the public URL from outside AWS and alerts when the entire VPS is unreachable

An important distinction we learned while operating the private VM and now on Lightsail:

Dozzle monitors the services inside the VPS. If the entire Lightsail instance becomes unreachable, Dozzle also becomes unavailable.

Internal monitoring answers “did my container restart?” External monitoring answers “is the whole machine reachable from the internet?” We need both, and we page differently for each.

Why PostgreSQL is still self-hosted

Our current choice remains AWS Lightsail + self-hosted PostgreSQL rather than immediately returning to RDS.

The reasoning is:

  • Beta-scale workload
  • Application and database can currently share the machine
  • Actual resource usage is manageable at 2 GB
  • We can operate backups and restores
  • Managed PostgreSQL is not currently necessary for the workload

We are explicit about when this decision would change:

  • Significant database growth or higher traffic
  • Sustained resource pressure
  • Need for managed point-in-time recovery without operating it ourselves
  • Multi-AZ or higher availability requirements
  • Inability to maintain backups and restores
  • Operational burden becoming too high

That is the same five-check lens we apply in our open-source evaluation guide and in every Stack Review. As we note in our cost breakdown, saving about $20 while spending five hours maintaining infra is not a saving at a founder hourly rate.

When we would change again

We would reconsider Lightsail if:

  • Memory pressure on 2 GB becomes sustained and verified (not just a brief spike)
  • We need managed PITR, multi-AZ, or an uptime story we cannot staff on a single instance
  • The team cannot own the restore drill that month

If any of those become true, the honest call may be a larger Lightsail instance — or back to managed Postgres — not “more tuning on 2 GB.” We keep a written rollback plan, just as we keep a scope cut list for product.

What we actually learned

Each infrastructure decision was correct for the problem we were solving at that time:

EC2 + RDS → optimize for managed infrastructure and less operational burden

₹520 private VM → optimize for cost, raw resources, and low latency

AWS Lightsail → optimize for predictable infrastructure, stable networking, operational confidence, and simplicity

We didn’t keep changing infrastructure because we couldn’t decide. We changed it because the constraints changed — and each move taught us what mattered next.

Choosing between managed and self-hosted Postgres? Run the same five checks we use — business fit, team capability, true cost with hours, security, and migration risk. Want us to run it with you? Run the Five Checks With Us or book a Stack Review — we will tell you to stay managed if that is the better trade.

We document the historical self-host details in our self-hosted Postgres field note and the hosted-vs-managed framework in our cost breakdown and how we ship in 28 days. For live pricing, verify current Lightsail pricing at aws.amazon.com/lightsail/pricing — do not re-price from our July 2026 $39 snapshot.

BOOK A CALL

Ready to turn your idea into a live product?

Schedule a 15-minute scoping call with Dhanji below. We'll discuss your scope, timeline, and tech strategy honestly.