Event Seat Booking on Website

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1 servicesAll 2065 services
Event Seat Booking on Website
Complex
~2-4 weeks
FAQ

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1262
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    874
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    851

Implementing Event Seat Booking on a Website

Event seat booking differs from other types: seats are fixed on a venue map, sales come in waves (early bird → general sale → last chance), and load can peak at sales start.

Data Model

CREATE TABLE events (
    id              SERIAL PRIMARY KEY,
    title           VARCHAR(255) NOT NULL,
    description     TEXT,
    venue_name      VARCHAR(255),
    venue_address   TEXT,
    starts_at       TIMESTAMP NOT NULL,
    ends_at         TIMESTAMP,
    sales_open_at   TIMESTAMP,
    sales_close_at  TIMESTAMP,
    status          VARCHAR(20) DEFAULT 'draft',  -- draft|on_sale|sold_out|finished
    schema_id       INTEGER,     -- venue map
    cover_image     VARCHAR(500)
);

CREATE TABLE seat_categories (
    id          SERIAL PRIMARY KEY,
    event_id    INTEGER REFERENCES events(id),
    name        VARCHAR(100),   -- 'Orchestra', 'Balcony', 'VIP'
    color       VARCHAR(7),     -- color on venue map
    price       NUMERIC(10,2),
    total_seats INTEGER,
    available_seats INTEGER
);

CREATE TABLE seats (
    id          BIGSERIAL PRIMARY KEY,
    event_id    INTEGER REFERENCES events(id),
    category_id INTEGER REFERENCES seat_categories(id),
    row_label   VARCHAR(10),
    seat_number VARCHAR(10),
    x_pos       NUMERIC(6,2),   -- coordinate on map
    y_pos       NUMERIC(6,2),
    status      VARCHAR(20) DEFAULT 'available',
    -- available | held | sold | blocked | unavailable
    booking_id  BIGINT,
    held_until  TIMESTAMP,
    held_by     VARCHAR(100)   -- session_id
);

CREATE TABLE ticket_bookings (
    id              BIGSERIAL PRIMARY KEY,
    event_id        INTEGER REFERENCES events(id),
    customer_name   VARCHAR(255),
    customer_email  VARCHAR(255),
    customer_phone  VARCHAR(50),
    total_amount    NUMERIC(10,2),
    status          VARCHAR(20) DEFAULT 'pending',
    payment_id      VARCHAR(100),
    created_at      TIMESTAMP DEFAULT NOW(),
    paid_at         TIMESTAMP,
    cancelled_at    TIMESTAMP
);

CREATE TABLE ticket_booking_seats (
    booking_id  BIGINT REFERENCES ticket_bookings(id),
    seat_id     BIGINT REFERENCES seats(id),
    price       NUMERIC(10,2),
    PRIMARY KEY (booking_id, seat_id)
);

Seat Hold with TTL

When the client selects seats, they are temporarily blocked until payment completes or timer expires:

HOLD_TTL_SECONDS = 600  # 10 minutes

def hold_seats(seat_ids: list[int], session_id: str) -> bool:
    with db.transaction():
        # Atomically check and block
        result = db.execute("""
            UPDATE seats
            SET status = 'held',
                held_by = %(session)s,
                held_until = NOW() + INTERVAL '10 minutes'
            WHERE id = ANY(%(ids)s)
              AND status = 'available'
            RETURNING id
        """, {'ids': seat_ids, 'session': session_id})

        held_count = len(result)
        if held_count < len(seat_ids):
            # Not all seats available — rollback transaction
            raise db.Rollback("Some seats are no longer available")

    return True

Expired holds are released by a background process running every minute:

UPDATE seats
SET status = 'available', held_by = NULL, held_until = NULL
WHERE status = 'held' AND held_until < NOW();

Venue Map (Seat Map)

Venue layout is rendered on SVG or Canvas. Seat data is requested from backend:

{
  "sections": [
    {
      "id": 1,
      "name": "Orchestra",
      "rows": [
        {
          "label": "A",
          "seats": [
            { "id": 1001, "number": "1", "x": 100, "y": 200, "status": "available", "price": 2500 },
            { "id": 1002, "number": "2", "x": 130, "y": 200, "status": "sold", "price": 2500 }
          ]
        }
      ]
    }
  ]
}

User clicks a seat, it highlights, gets added to cart. On attempt to add already taken seat — error shows without page reload (WebSocket or polling every 5 sec).

Real-Time Updates

During high demand, seats are snapped up fast. Real-time schema updates via WebSocket:

const ws = new WebSocket(`wss://api.example.com/events/${eventId}/seats`);

ws.onmessage = (event) => {
  const { seat_id, status } = JSON.parse(event.data);
  updateSeatStatus(seat_id, status);  // update color on map
};

Backend broadcasts updates to all connected clients on each seat status change.

Pricing Categories and Sales Waves

CREATE TABLE pricing_tiers (
    id              SERIAL PRIMARY KEY,
    event_id        INTEGER REFERENCES events(id),
    name            VARCHAR(100),   -- 'Early Bird', 'Standard'
    category_id     INTEGER REFERENCES seat_categories(id),
    price           NUMERIC(10,2),
    available_from  TIMESTAMP,
    available_until TIMESTAMP,
    quota           INTEGER         -- seat limit at this price
);

System automatically switches between tiers on schedule.

E-Tickets

After payment, each ticket is generated as PDF with QR code:

import qrcode
from reportlab.pdfgen import canvas

def generate_ticket_pdf(ticket: dict) -> bytes:
    qr = qrcode.make(ticket['verification_code'])
    # ... overlay QR on PDF template
    return pdf_bytes

QR contains a signed token with ticket_id and booking_id. At entry — scanned and verified via API.

Implementation Timeline

Without venue map, simple seat numbering, online payment — 10–12 business days. Full seat map (SVG), real-time updates, e-tickets with QR, pricing tiers, entry verification — 16–22 business days.