I think the best place to run your expensive function is in the form itself, even though you've mentioned you're currently avoiding that. As it stands, your page callback has no link to the form that's currently being submitted; there are ways you could get it from the `cache_form` table, but it's a bit messy. Instead, I'd advise saving the data to a variable in the form, and checking to see if that variable has been submitted in the `$form_state` array: function test_simple_form(&$form_state) { // If the form has already been biult, and we already have the data, don't load it again. if (isset($form_state['values']['expensive_data'])) { $data = $form_state['values']['expensive_data']; } else { // Otherwise get the data from source. $data = my_expensive_function(); } // Store the data $form['expensive_data'] = array( '#type' => 'value', '#value' => $data ); // ... return $form; } In your submit handler you'll have access to `$form_state['values']['expensive_data']`, which will contain the results of the function call. This method has the added benefit of caching the data if the form validation fails, not just when it's submitted successfully. Judging from the function signature you're using for the form I'm guessing you have a Drupal 6 site, although the above method will work equally well for a Drupal 7 site (the function signature would just need to change).