WordPress Dhaka Meetup · 29 August 2026
Don't use AI to only write more code.
Prime once. Read many.
// BEFORE
foreach ($user_ids as $user_id) {
$plan = get_user_meta($user_id, 'plan', true);
}
// AFTER
update_meta_cache('user', $user_ids);
foreach ($user_ids as $user_id) {
$plan = get_user_meta($user_id, 'plan', true);
}
The user should not wait for work they don't need now.
// BEFORE
add_action('save_post', function ($post_id) {
sync_to_crm($post_id);
send_digest($post_id);
});
// AFTER — Action Scheduler
add_action('save_post', function ($post_id) {
as_enqueue_async_action(
'myplugin/process_post',
[$post_id],
'myplugin'
);
});
Cache is easy. Invalidation is the design.
$key = "stats:$user_id";
$stats = wp_cache_get($key, 'myplugin');
if (false === $stats) {
$stats = calculate_stats($user_id);
wp_cache_set(
$key,
$stats,
'myplugin',
300
);
}
A hook should trigger behavior — not become the application.
// BEFORE
add_action('save_post_course', function ($post_id) {
// validate
// business rules
// database writes
// email
// analytics
});
// AFTER
add_action(
'save_post_course',
[$course_saved, 'handle']
);
Framework at the edge. Business rules in the middle.
// COUPLED
function discount_for($user_id): int {
$roles = get_userdata($user_id)->roles;
return in_array('vip', $roles, true) ? 20 : 0;
}
// PORTABLE
final class DiscountPolicy {
public function for(Customer $customer): int {
return $customer->isVip() ? 20 : 0;
}
}
Indexes follow access patterns — not intuition.
EXPLAIN
SELECT id
FROM wp_myplugin_orders
WHERE customer_id = 42
AND status = 'paid'
ORDER BY created_at DESC
LIMIT 50;
CREATE INDEX idx_customer_status_created
ON wp_myplugin_orders (
customer_id,
status,
created_at
);