Get all user meta by meta key instead of ID

Two options. The first will keep you away from custom SQL, and should be a lot more efficient than what you currently have.

It runs two queries, one to get the user ID with the highest hourly rate, and then again to get the lowest. You need one more query to update the user meta cache & then you’re home free:

$query = new WP_User_Query;
$users = array(
    'min_user' => 'ASC',
    'max_user' => 'DESC',
);

foreach ( $users as $var => $order ) {
    $query->query(
        array(
            'count_total' => false, // Save SQL_CALC_FOUND_ROWS, don't need it
            'meta_key' => 'hourly_rate',
            'orderby' => 'meta_value',
            'fields' => 'ID', // Don't waste memory
            'number' => 1, // Just need the first user ID of the result
            'order' => $order,
        )
    );

    if ( $data = $query->get_results() )
        $$var = $data[0]; // User ID
    else
        $$var = 0;
}

update_meta_cache( 'users', array( $min_user, $max_user ) );

echo get_post_meta( $max_user, 'hourly_rate', true ); // Highest hourly rate
echo get_post_meta( $min_user, 'hourly_rate', true ); // Lowest hourly rate

The second is one custom SQL query:

$rates = $wpdb->get_row( "SELECT MAX( CAST( meta_value AS UNSIGNED ) ) AS max_rate, MIN( CAST( meta_value AS UNSIGNED ) ) AS min_rate FROM $wpdb->usermeta WHERE meta_key = 'hourly_rate'" ); 

echo $rates->max_rate;
echo $rates->min_rate;

Doesn’t get much leaner than that!