A method implemented at least in part by a computer, the method comprising: commencing execution of a program; while executing code of the program, encountering a first asynchronous operation, an asynchronous operation being an operation that completes independently of the main program flow; checking a history store to determine whether a response to the first asynchronous operation has been received; if a response has been received (320, Y), obtaining completion data from the history store and providing the completion data to the program code; if a response has not been received (320, N), performing the following actions: scheduling a task to make a request to an asynchronous component (205 - 207) suitable for the asynchronous operation and, when the program code is blocked on the first asynchronous operation completing, removing the program code from memory; waiting for a response to be received from the asynchronous component (205 - 207); when a response is received, placing completion data corresponding to the response in the history store; providing a notification that a response has been received; loading the program code into memory and commencing re-executing the program; while re-executing the code of the program encountering the first asynchronous operation again and providing the completion data to the program code. commencing execution of a program; while executing code of the program, encountering a first asynchronous operation, an asynchronous operation being an operation that completes independently of the main program flow; checking a history store to determine whether a response to the first asynchronous operation has been received; if a response has been received (320, Y), obtaining completion data from the history store and providing the completion data to the program code; if a response has not been received (320, N), performing the following actions: scheduling a task to make a request to an asynchronous component (205 - 207) suitable for the asynchronous operation and, when the program code is blocked on the first asynchronous operation completing, removing the program code from memory; waiting for a response to be received from the asynchronous component (205 - 207); when a response is received, placing completion data corresponding to the response in the history store; providing a notification that a response has been received; loading the program code into memory and commencing re-executing the program; while re-executing the code of the program encountering the first asynchronous operation again and providing the completion data to the program code. scheduling a task to make a request to an asynchronous component (205 - 207) suitable for the asynchronous operation and, when the program code is blocked on the first asynchronous operation completing, removing the program code from memory; waiting for a response to be received from the asynchronous component (205 - 207); when a response is received, placing completion data corresponding to the response in the history store; providing a notification that a response has been received; loading the program code into memory and commencing re-executing the program; while re-executing the code of the program encountering the first asynchronous operation again and providing the completion data to the program code.