refactor to support multiple backends