Muroom is a map-first search service for music practice studios in Seoul. Musicians pan a map; every studio inside the viewport appears as a price-tagged marker and as a card in a synced list, filterable across thirteen dimensions: price, room size, floor type, parking, lodging, fire insurance, forbidden instruments, and per-category amenities. Each listing shows rooms with per-room pricing, building facts, and straight-line distances to up to three nearby subway stations.
The supply side was operations, not self-serve: we cold-called studio owners, collected their floor plans and room specs, and registered 130 studios (1,273 rooms) through an internal admin flow. Owner accounts exist for every studio, but owner-facing self-registration was still being built when the project wound down; an eight-step wizard with JSONB-backed draft saves was the last feature in flight.
Under the hood it's a deliberately boring stack doing a few interesting things: one Spring Boot monolith, PostgreSQL with PostGIS for viewport queries, addresses geocoded through Korea's public road-address API (with an EPSG:5179→WGS84 transform), sessions over JWT, and the whole AWS footprint defined in Terraform at ~$150/month for two environments.
Architecture
A single Spring Boot service on ECS (EC2, Graviton) behind one ALB that host-routes prod and dev; data lives on self-managed EC2 instances (PostgreSQL 17 + PostGIS, and Valkey), with images uploaded browser-direct to S3 via presigned URLs. Credentials rotate through a Secrets Manager Lambda that the app survives without redeploys, and all egress rides a single t4g.nano NAT instance. Everything below the DNS line is Terraform.
SSM (no SSH)readiness gatingWAL→S3 10scalendar-versioned deploysAI code review
Who did what
Five people. I owned the company and two slices of the product, not all of it.
Monte (me)Founder
Company and fundraising as registered CEO. Geospatial search and the studio domain with its file-storage engine, every schema migration, all AWS infrastructure and Terraform, every deploy.
Backend engineer
Authentication (OAuth, sessions, SMS verification) and the member-facing domains: my-page, terms, reports, inquiries.
Frontend engineer
The entire web client in Next.js: map view, filters, listing pages.
Designers ×2
Product design and brand identity across the service.
Timeline
Oct 2025
First commit
Idea validated by phone first: 110 cold calls before and during the build.
Nov 2025
Beta live on AWS, three weeks in
Dockerised, prod profile, running on AWS from commit twenty-something.
Dec 2025
Soft launch: first real users
549 searches and 14 sign-ups in December; supply kept growing by cold call.
Feb 2026
Terraform migration, RDS → self-managed EC2
The whole footprint became code; the data tier moved off managed services to fit a pocket-money budget.
Feb 2026
Last production deploy
Development continued on branches; operations stayed quiet.
May 2026
Operations paused
The team turned to job searches; the service kept running on credits.
Aug 2026
Wound down
Credits exhausted. Data archived, infrastructure torn down, postmortems published.
Decisions worth reading about
RDS → self-managed Postgres on EC2
Server bills were coming out of our own pockets, so I traded managed guarantees for ~$150/mo across two environments, then rebuilt the guarantees by hand: 3-layer backups, WAL shipping every 10s, and RDS-grade credential rotation on a database AWS doesn't manage.
The paid directions API billed per studio per page; the free public alternative was rate-limited to unusability. We deleted the feature and compute Haversine in Java: strictly worse information, strictly zero marginal cost.
Once refresh-token revocation forced state into Redis, JWT was sessions with extra steps. I proposed the switch; JWT survives only as short-lived handshake tokens.
App-generated 64-bit time-sortable PKs killed a per-INSERT round-trip; two days later JavaScript's 2⁵³ limit silently truncated them, and every API ID became a string the same afternoon.
On working-engineer advice: relax the database, enforce in code. Fourteen FKs went; creation-time existence checks and service-owned cascade deletes took their place, with partial unique indexes handling soft-delete uniqueness.