code: @Override
    public UpdateResponse deleteFlowConfig(FlowId flowId, Properties header)
        throws FlowConfigLoggedException {
      String flowName = flowId.getFlowName();
      String flowGroup = flowId.getFlowGroup();
  
      checkHelixConnection(ServiceConfigKeys.HELIX_FLOWSPEC_REMOVE, flowName, flowGroup);
  
      try {
        if (!jobScheduler.isActive() && helixManager.isPresent()) {
  
          if (this.flowCatalogLocalCommit) {
            // We will handle FS I/O locally for load balance before forwarding to remote node.
            this.localHandler.deleteFlowConfig(flowId, header, false);
          }
  
          forwardMessage(ServiceConfigKeys.HELIX_FLOWSPEC_REMOVE, FlowConfigUtils.serializeFlowId(flowId), flowName, flowGroup);
  
          return new UpdateResponse(HttpStatus.S_200_OK);
        } else {
          return this.localHandler.deleteFlowConfig(flowId, header);
        }
      } catch (IOException e) {
        throw new FlowConfigLoggedException(HttpStatus.S_500_INTERNAL_SERVER_ERROR,
            "Cannot delete flowConfig [flowName=" + flowName + " flowGroup=" + flowGroup + "]", e);
      }
    }
docs: Deleting {@link FlowConfig} should check if current node is active (master).
  If current node is active, call {@link FlowConfigResourceLocalHandler#deleteFlowConfig(FlowId, Properties)} directly.
  If current node is standby, forward {@link ServiceConfigKeys#HELIX_FLOWSPEC_REMOVE} to active. The remote active will
  then call {@link FlowConfigResourceLocalHandler#deleteFlowConfig(FlowId, Properties)}.
  
  Please refer to {@link org.apache.gobblin.service.modules.core.ControllerUserDefinedMessageHandlerFactory} for remote handling.
  
  For better I/O load balance, user can enable {@link GobblinServiceFlowConfigResourceHandler#flowCatalogLocalCommit}.
  The {@link FlowConfig} will be then persisted to {@link org.apache.gobblin.runtime.spec_catalog.FlowCatalog} first before it is
  forwarded to active node (if current node is standby) for execution.