diff --git a/cmd/protoc-gen-goclay/genhandler/handler.go b/cmd/protoc-gen-goclay/genhandler/handler.go
index f16af31..4f695a5 100644
--- a/cmd/protoc-gen-goclay/genhandler/handler.go
+++ b/cmd/protoc-gen-goclay/genhandler/handler.go
@@ -99,6 +99,31 @@ func (g *Generator) generateDesc(file *descriptor.File) (*plugin.CodeGeneratorRe
 	}, nil
 }
 
+func (g *Generator) generateSwaggerFile(file *descriptor.File) *plugin.CodeGeneratorResponse_File {
+	if g.options.SwaggerPath == "" || len(g.options.SwaggerDef) == 0 {
+		return nil
+	}
+
+	swaggerContent := g.options.SwaggerDef[file.GetName()]
+	if swaggerContent == nil {
+		return nil
+	}
+
+	name := filepath.Base(file.GetName())
+	ext := filepath.Ext(name)
+	base := strings.TrimSuffix(name, ext)
+
+	output := fmt.Sprintf(filepath.Join(g.options.SwaggerPath, "%s.json"), base)
+	output = filepath.Clean(output)
+
+	glog.V(1).Infof("Will emit %s", output)
+
+	return &plugin.CodeGeneratorResponse_File{
+		Name:    proto.String(output),
+		Content: proto.String(string(swaggerContent)),
+	}
+}
+
 func (g *Generator) generateImpl(file *descriptor.File) (files []*plugin.CodeGeneratorResponse_File, err error) {
 	guessModule()
 	var pkg *ast.Package
@@ -242,6 +267,10 @@ func (g *Generator) Generate(targets []*descriptor.File) ([]*plugin.CodeGenerato
 			return nil, err
 		}
 
+		if swaggerFile := g.generateSwaggerFile(file); swaggerFile != nil {
+			files = append(files, swaggerFile)
+		}
+
 		if g.options.Impl {
 			if code, err := g.generateImpl(file); err == nil {
 				files = append(files, code...)
diff --git a/cmd/protoc-gen-goclay/genhandler/options.go b/cmd/protoc-gen-goclay/genhandler/options.go
index e427bcc..a069be1 100644
--- a/cmd/protoc-gen-goclay/genhandler/options.go
+++ b/cmd/protoc-gen-goclay/genhandler/options.go
@@ -4,6 +4,7 @@ type options struct {
 	ImplPath                string
 	DescPath                string
 	SwaggerDef              map[string][]byte
+	SwaggerPath             string
 	Impl                    bool
 	Force                   bool
 	ServiceSubDir           bool
@@ -21,6 +22,13 @@ func SwaggerDef(swaggerDef map[string][]byte) Option {
 	}
 }
 
+// SwaggerPath sets path to store separate swagger files
+func SwaggerPath(swaggerPath string) Option {
+	return func(o *options) {
+		o.SwaggerPath = swaggerPath
+	}
+}
+
 // ApplyDefaultMiddlewares toggles application of httpruntime/httpmw.DefaultChain to
 // every generated handler.
 func ApplyDefaultMiddlewares(apply bool) Option {
diff --git a/cmd/protoc-gen-goclay/main.go b/cmd/protoc-gen-goclay/main.go
index df6e4fc..4a666d5 100644
--- a/cmd/protoc-gen-goclay/main.go
+++ b/cmd/protoc-gen-goclay/main.go
@@ -22,6 +22,7 @@ var (
 	grpcAPIConfiguration = flag.String("grpc_api_configuration", "", "path to gRPC API Configuration in YAML format")
 	withImpl             = flag.Bool("impl", false, "generate simple implementations for proto Services. Implementation will not be generated if it already exists. See also `force` option")
 	withSwagger          = flag.Bool("swagger", true, "generate swagger.json")
+	withSwaggerPath      = flag.String("swagger_path", "", "in addition to swagger in pb.goclay.go, generate separate swagger file at provided path")
 	applyHTTPMiddlewares = flag.Bool("http_middlewares", true, "apply default HTTP millewares")
 	implPath             = flag.String("impl_path", "", "path where the implementation is generated (for impl = true)")
 	forceImpl            = flag.Bool("force", false, "force regenerate implementation if it already exists (for impl = true)")
@@ -112,6 +113,10 @@ func main() {
 		opts = append(opts, genhandler.SwaggerDef(swagBuf))
 	}
 
+	if *withSwaggerPath != "" {
+		opts = append(opts, genhandler.SwaggerPath(*withSwaggerPath))
+	}
+
 	g := genhandler.New(reg, opts...)
 
 	var targets []*descriptor.File