Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I still use FCGI. FCGI works a lot like CGI; it loads programs when a request comes in, and the programs deal with the request. But it's much higher performance, because it doesn't have to freshly load the target program each time.

FCGI is an orchestration system. It starts up more worker processes if there are more requests, up to some limit it figures out by itself. If there are few requests, some of the worker processes get an end of file notification and exit. If a worker process crashes, it loads a fresh copy. Little or no human attention required. One of my systems has been up for 1788 days now.

FCGI works fine with Go programs, Python programs, etc. If you use Go, you can get performance reasonably close to what the hardware can do. Until you get to the point that you're renting additional servers as load increases, you don't need more than that for most applications.

You can run FCGI on some cheap shared hosting systems. Why pay more?



I'm really interested in this. How do you handle DB connections? I guess each CGI file becomes stateful because it's not reloaded all the time, and there's a connection handle there.


> How do you handle DB connections?

Look at

https://github.com/John-Nagle/vehiclelogserver, which has database connections.

Each FCGI program has a database connection. That database connection persists as long as the program instance is running. So it's not establishing a new database connection for each transaction.


for Go, do you rely on `net/http/fcgi` to run it? Do you have any example i can have a look at?


> for Go, do you rely on `net/http/fcgi` to run it?

Yes.

> Do you have any example I can have a look at?

https://github.com/John-Nagle/vehiclelogserver/blob/master/v...

There's not much machinery required.

    package main
    import (
        "database/sql"
        "net/http"
        "net/http/fcgi"
    )

    //
    //  Called by FCGI for each request
    //
    func (sv FastCGIServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
        body := make([]byte, 5000) // buffer for body, which should not be too big
        if req.Body != nil {
            len, _ := req.Body.Read(body)          // body of HTTP request
            bodycontent := body[0:len]             // take correct part of buffer
            Handlerequest(sv, w, bodycontent, req) // handle request
        }
    }

    //  Run FCGI server
    func main() {
        sv := new(FastCGIServer)
        fcgi.Serve(nil, sv)
    }

    //  Handlerequest -- handle one request from a client
    func Handlerequest(sv FastCGIServer, w http.ResponseWriter, bodycontent []byte, 
        req *http.Request) {
        // GENERATE REPLY CONTENT HERE
        w.WriteHeader(statuscode)           // internal server error
        w.Write(content) // report error as text ***TEMP***
    }
That will run on low-end hosting at Dreamhost.

So there you are, in a modern language, with hard-compiled code with good performance, and reasonably good fault tolerance. Next step up would be a load balancer and redundant databases.




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: