Building distributed applications with step functions