OK @Asb comment got me thinking that everyone seems to be fine with the lora.has_joined() method call. So I put a slight delay following the nvram_restore call, and it seems to work ok. 2 seconds seems to be optimal. This code seems to work most of the time. lora = LoRa(mode=LoRa.LORAWAN) lora.nvram_restore(): time.sleep(2) if not lora.has_joined(): print('failed to join via nvram_restore') lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AU915, adr=False, tx_retries=0, device_class=LoRa.CLASS_A) for i in range(16, 65): #AU915 TTN gateways need channels removed lora.remove_channel(i) for i in range(66, 72): lora.remove_channel(i) appeui = binascii.unhexlify(app_eui) appkey = binascii.unhexlify(app_key) lora.join(activation=LoRa.OTAA, auth=(appeui, appkey), timeout=0) while not lora.has_joined(): print('trying to join OTAA') time.sleep(0.5) print('connected and ready to publish') s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) s.setblocking(True) s.send("some data") s.setblocking(False) rev_data = s.recv(64) print('recieved data: ', rev_data) lora.nvram_save() time.sleep(2)