Skip to main content
NetterTech
Event management for WordPress, done right.

Why we built NetterTech Events on custom database tables

This post is for developers, agency engineers, and technically curious venue operators who want to understand why NetterTech Events uses custom database tables instead of the standard WordPress post_meta approach. If you don’t care how the engine works, only that it’s fast, the short version is: custom tables are faster, safer, and more maintainable for structured event data.

The Post Meta Problem

WordPress stores custom data in the wp_postmeta table, a key-value store with four columns: meta_id, post_id, meta_key, and meta_value. This pattern works for simple metadata (a subtitle, a color setting, a toggle). It breaks down for structured, relational data like events.

An event has a start date, end date, venue, capacity, recurrence pattern, ticket types, attendee records, and check-in states. Storing all of this in post_meta means:

Query performance degrades. Fetching “all events in March sorted by date” requires JOINing wp_postmeta on wp_posts, filtering on meta_key = ‘_event_start_date’, casting meta_value to a date, and sorting. With thousands of events, this query slows measurably.

No data typing. meta_value is a LONGTEXT column. Dates, integers, booleans, and JSON all live in the same text field. MySQL can’t use native date comparison or integer indexing on text values.

No referential integrity. There’s no foreign key between an event and its ticket types or attendees. Orphaned meta rows accumulate. Cascade deletes require application-level logic.

Indexing limitations. wp_postmeta has indexes on post_id and meta_key, but not on meta_value. You can’t efficiently query “events where capacity > 100” or “events at venue X” without full table scans on large installations.

What Custom Tables Look Like

NetterTech Events uses 20 dedicated tables (prefixed nte_). Here are the core five:

TablePurposeKey Columns
wp_nte_eventsEvent definitionsid, title, start_date, end_date, venue_id, status, recurrence_rule
wp_nte_occurrencesPre-computed occurrencesid, event_id, start_date, end_date
wp_nte_ticket_typesTicket definitionsid, event_id, name, price, capacity
wp_nte_attendeesRegistration recordsid, event_id, occurrence_id, name, email
wp_nte_ticketsIndividual ticketsid, attendee_id, ticket_type_id, qr_code, checked_in

Additional tables handle series, spaces, organizers, categories, tags, attendee custom fields, activity logs, reservations, waitlists, reminders, and event revisions. Each table has typed columns (DATETIME, INT, DECIMAL), proper indexes, and foreign key relationships.

The Performance Difference

Calendar Query: “Show all events in March 2026”

Post meta approach:

SELECT p.* FROM wp_posts p
INNER JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE pm.meta_key = '_event_start_date'
AND CAST(pm.meta_value AS DATETIME) BETWEEN '2026-03-01' AND '2026-03-31'
AND p.post_status = 'publish'
ORDER BY CAST(pm.meta_value AS DATETIME);

This requires a JOIN, a CAST on every row, and can’t use an index on the date value. On a site with 10,000 events and 500,000 meta rows, this query takes measurable time.

Custom table approach:

SELECT * FROM wp_nte_occurrences
WHERE start_date BETWEEN '2026-03-01' AND '2026-03-31'
ORDER BY start_date;

Native DATETIME column, indexed, no JOIN. O(log n) lookup.

Capacity Check: “How many tickets remain for occurrence X?”

Post meta approach: Multiple JOINs across posts, postmeta (for capacity), and WooCommerce order items (for sold count). Application-level aggregation.

Custom table approach:

SELECT tt.capacity - COUNT(t.id) AS remaining
FROM wp_nte_ticket_types tt
LEFT JOIN wp_nte_tickets t ON t.ticket_type_id = tt.id
WHERE tt.event_id = ?
GROUP BY tt.id;

Single query, typed columns, indexed joins.

Why Most Plugins Don’t Do This

Custom tables require more engineering work:

  • Schema management. You need activation hooks to create tables, upgrade routines to migrate schemas, and uninstall hooks to clean up. WordPress doesn’t provide scaffolding for this.
  • No admin UI for free. Post types get list tables, editors, and meta boxes from WordPress core. Custom tables need custom admin pages built from scratch.
  • Search integration. WordPress search queries wp_posts. Custom table data is invisible to the default search unless you build a bridge. NetterTech Events uses a shadow post type to index event data into WordPress search.
  • Plugin review. WordPress.org reviewers sometimes scrutinize custom table usage. The tables need to follow WordPress conventions (prefix with $wpdb->prefix, use dbDelta() for creation).

These are real costs. For simple plugins, post_meta is the pragmatic choice. For event management, with its relational data, date queries, and capacity math, custom tables are the architecturally sound choice.

What This Means for You

For venue operators:

  • Faster calendar pages, especially as your event count grows
  • Reliable capacity tracking (no race conditions from meta-based counting)
  • Clean data exports (structured tables, not key-value soup)

For developers:

  • Direct SQL access to typed, indexed columns
  • Foreign key relationships between events, occurrences, tickets, and attendees
  • A schema you can inspect with DESCRIBE wp_nte_events instead of guessing meta_key names
  • Over 5,500 unit tests validating the data layer

For agencies:

  • Predictable performance across client sites with varying event volumes
  • Database-level integrity instead of application-level validation
  • Easier debugging (query the table directly, not meta archaeology)

Trade-Offs

Custom tables aren’t free of downsides:

  • WP-CLI integration. Standard wp post list doesn’t know about custom tables. We provide our own WP-CLI commands for event management.
  • Backup tools. Some WordPress backup plugins only back up core tables by default. Make sure your backup solution includes custom tables (most do, but verify).
  • Migration complexity. Moving between plugins means mapping custom schemas. The NetterTech Events Migrator handles this for common sources (TEC, BPT, etc.).

Further Reading


Install free or view plans to get started.