WE DON’T DO THIS
def do_everything(request):
hotel_id = request.GET.hotel_id
room_number = request.GET.room_number
with room_mutex(hotel_id, room_number):
room = (session.query(Room)
.filter(Room.hotel_id == hotel_id)
.filter(Room.room_number == room_number).one())
if not room.available:
return Response("Room not available”,
template=room_template)
reservation = Reservation(client=request.client, room=room)
session.add(reservation)
room.available = False
price = # price_calculation
payment = Payment(reservation=reservation, price=price)
session.add(payment)
session.commit()
url = payment.get_psp_url()
return Redirect(url)
BUT WE DO THIS
• Frontend UI
• Locking rooms
• Calculating room availability
• Temporarily locking rooms
• Payment processing
• Mail
• PDF invoice generation
TECHNOLOGY
• Monitoring: nagios, ganglia, pingdom
• Email: offloaded to StrongMail
• Load-balanced read slave pool
• Feature flags
• Automated server configuration and
release with Puppet and Jenkins
TECHNOLOGY
• Feature flags
• Develop on Vagrant
• Celery + RabbitMQ
• Virtual customer queue
• Big data for reporting, fraud, spam,
event recommendations
SCALING STORAGE
• Move to NoSQL
• Aggressively move queries to slaves
• Different indexes per slave
• Better hardware
• Most optimal tables for large and
highly-utilized datasets
FIRST ATTEMPT
CREATE TABLE `user_emails` (
`id` int NOT NULL AUTO_INCREMENT,
`email_address` varchar(255) NOT NULL,
... --other columns about the user
`user_id` int, --foreign key to users
KEY (`email_address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LESSONS
• Do work once, distribute results.
• Most likely to fail: your code. Don’t
reinvent. Keep team small.
• End-to-end ACKs are expensive.
Avoid.
• Understand use cases when load
testing.
• Tune architecture to scale.